2016-06-28 3 views
4

아래의 코드 예에서 accessUsingReflection ->theAnswer.get(outer)IllegalAccessException인데 반해 accessDirectly은 42를 올바르게 인쇄합니까?리플렉션을 사용하여 외부 클래스의 private 멤버에 액세스하는 이유는 무엇입니까? IllegalAccessException?

Exception in thread "main" java.lang.IllegalAccessException: Class Outer$Inner can not access a member of class Outer with modifiers "private" 

this SO answer에 따르면, 나는 "그것을 액세스 할 수있는 클래스에서 (...)"액세스가 발생합니까대로 일을 기대.

import java.lang.reflect.Field; 

public class Outer 
{ 
    private int theAnswer = 42; 

    public static class Inner 
    { 
     public void accessDirectly(Outer outer) 
     { 
     System.out.println(outer.theAnswer); 
     } 

     public void accessUsingReflection(Outer outer) throws NoSuchFieldException, 
                 SecurityException, 
                 IllegalArgumentException, 
                 IllegalAccessException 
     { 
     Field theAnswer = Outer.class.getDeclaredField("theAnswer"); 
     // Of course, uncommenting the next line will make the access using reflection work. 
     // field.setAccessible(true); 
     System.out.println(theAnswer.get(outer)); 
     } 
    } 

    public static void main(String[] args) throws NoSuchFieldException, 
              SecurityException, 
              IllegalArgumentException, 
              IllegalAccessException 
    { 
     Outer outer = new Outer(); 
     Inner inner = new Inner(); 
     inner.accessDirectly(outer); 
     inner.accessUsingReflection(outer); 
    } 
} 

답변

2

"왜"왜 이런 질문을하면 대답이 까다로울 수 있습니까? 을 비롯한 많은 이유가 있습니다. 이유는 무엇입니까?사양의 어떤 부분에서 이것을 허용합니까?기본 기술 정보는 무엇입니까?

나는 그 중 마지막 답변을 하겠지만, 그게 당신이 쫓고 있는지 확실하지 않습니다.

Java 런타임 (JVM, 보안 모델 등)은 내부 클래스에 대해 거의 모릅니다. 그들은 대부분 언어 문제입니다.

컴파일러는 런타임에서 일반적으로 허용하지 않더라도 내부/외부 클래스가 서로의 개인 멤버에 액세스 할 수 있도록 숨겨진 트릭을 사용합니다.

그 중 하나는 사용자의 accessDirectly 메서드가 실제로 필드에 직접 액세스하지 않는다는 것입니다. 컴파일러는 theAnswer 값을 반환하는 외부 클래스에 숨겨진 메서드를 추가합니다.

필드 (theAnswer)는 여전히 개인이며 런타임 보안 모델과 관련하여 소유 (외부) 클래스 외부에서는 액세스 할 수 없습니다.

따라서 리플렉션 라이브러리에서 복제되지 않은 컴파일러의 특수한 동작에 의존하므로 리플렉션으로 수행 할 수없는 Java 코드에서 할 수있는 일이 있습니다.

당신이 읽을 수있는 더 here

+0

맞습니다. 저는 그 질문에 기술적 측면과 개념적 측면이있을 수 있다는 사실을 알고있었습니다. 그러나 당신의 포괄적 인 대답은 정확하게 내가 한 것입니다. –

0

때문에 그 사실, 같은 클래스에 public static void main(String[] args) 및 현장 private int theAnswer = 42 있습니다 귀하의 accessDirectly 인쇄 (42) 잘 (당신이 외부 클래스의 필드에 액세스 할 수 있습니다) 당신이 반사를 사용하는 경우, 그러나, 당신은 객체 Class를로드 Class Outer 필드 private int theAnswer = 42은 개인용입니다 (다른 클래스 개인 필드에 대한 액세스 권한 없음). field.setAccessible(true) 호출이 없으면 예외 java.lang.IllegalAccessException이 발생합니다.

this 예제 메서드는 동일한 클래스에서 호출하지만 내부 클래스 public static class Inner에서 호출하는 것입니다.

+1

그러나'에 직접 액세스 theAnswer' 내'main' 방법이 선언 된 같은 클래스에 발생하지 않습니다 - 그것은 내부 클래스 내에서 발생합니다. –

+0

예, 'inner' 클래스에서 직접 액세스하려고하면'outer' 클래스의 비공개 필드에 액세스 할 수 있습니다. – mrserfr

관련 문제