2013-10-15 4 views
2

한 친구가 저에게 보내는 스 니펫과 관련이 있습니다. 그것은 정말로 이상한 행동을했습니다. 나는 인터넷에서 무언가를 찾았는지 행운이 없는지 알아보기 위해 구글 코드를 시도했다. 나는 친구와 연락 할 수 없어, 그 일에 대해 무언가를했다.누구든지이 코드가 false를 반환하는 이유를 설명 할 수 있습니까

public class Test { 

     public static void main(String[] args) throws MalformedURLException { 
      System.out.println(Boolean.TRUE); //This prints false 
     } 

     static { 
      try { 
       Field value = Boolean.class.getDeclaredField("value"); 
       value.setAccessible(true); 
       value.set(Boolean.TRUE, value.get(Boolean.FALSE)); 
      } catch (Exception e) { 
       throw new AssertionError(e); 
      } 
     } 

    } 

가 나는 static으로 선언있어 코드의 조각처럼, 먼저 그 main 방법을 실행하고, 그 정적 코드 안에 모든 Boolean 인스턴스의 값을 변경하고, 생각 (?). 나도 모르겠다. 나는 이것을 확인하기 위해 전문가의 견해가 필요하다.

+0

'static' 섹션은 클래스가 처음로드 될 때 실행되는 정적 초기화 블록입니다. 이 블록은 정적 인 필드 'TRUE'의 값을'false'로 변경하기 위해 반사되는 부분을 사용합니다. 자세한 내용은 [필드 초기화] (http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html)를 참조하십시오. – MadProgrammer

답변

4
Field value = Boolean.class.getDeclaredField("value"); 
value.setAccessible(true); 
value.set(Boolean.TRUE, value.get(Boolean.FALSE)); 

트로프 반사는 Boolean.TRUE의 상수 값 Boolean.FALSE 설정된다. 그건 .. 정확히 코드에서 읽을 수있는 것입니다.

static 이니셜 라이저 블록이 main 메서드보다 먼저 실행되므로 나중에 발생한다고 생각하게 만들지 마세요.

견적 this 포스트에서 :

더 보안 관리자는이 일에서 당신을 방지하지 않습니다 가정하면, 최종 없애 개인과 수정을 재설정 해결하기 위해 setAccessible 사용하고, 실제로 개인 정적 최종를 수정할 수 있습니다 들.

+0

Okey, but Boolean.TRUE' 및' Boolean.FALSE' 상수는'final'으로 선언됩니다. 따라서 반성은 '최종'키워드를 속일 수 있습니까? – 4gus71n

+0

반사는 프로그래밍의 치트 코드입니다. 처음부터 불가능한 일을 처리 할 수 ​​있습니다. –

+0

그래, 나는 이상한 것을 많이 깨달았다. 먼저 Boolean.FALSE와 Boolean.TRUE는 둘 다 기본형이 아닌 Boolean 인스턴스입니다. 이 예제를 사용하여 프리미티브를 시도하면 모두 정상적으로 실행됩니다. 또한,'Boolean' 객체의'value' 필드는'final'이며 초기화되지 않습니다. 그래서 reflection을 가진 어딘가에서, 같은 Boolean 클래스는 자신의 value 필드 값을 변경해야합니다. 소년 당신은 이상한 자바 [Boolean.java] (http : //www.docjar. – 4gus71n

2

이것은 정적 초기화 블록이 클래스 인스턴스에 대한 다른 초기화 전에 실행될 것이라는 명령의 순서 때문입니다. 정적 초기화는 클래스가로드 될 때 수행됩니다. 일반적으로 클래스의 첫 번째 참조에서.

main 메서드가 호출되기 전에 정적 블록이 Boolean.TRUE 값을 변경하기 때문에 변경된 값이 인쇄됩니다.

는 다음 예 (source)을 고려해

/* 
* Here we will learn to see how the different part (Ananymous Block, Constructor and Static Block) of class will behave 
* and what would be the order of execution. 
*/ 
class JBTCLass { 

    /* 
    * Here Creating the Ananymous Block 
    */ 
    { 
     System.out.println("Inside Ananymous Block"); 
    } 

    /* 
    * Now Creating the Static Block in Class 
    */ 
    static { 
     System.out.println("Inside Static Block"); 
    } 

    /* 
    * Here Creating the Constructor of Class 
    */ 
    JBTCLass() { 
     System.out.println("Inside Constructor of Class"); 
    } 

    public static void main(String[] args) { 

     // Creating the Object of the Class 
     JBTCLass obj = new JBTCLass(); 

     System.out.println("*******************"); 

     // Again Creating Object of Class 
     JBTCLass obj1 = new JBTCLass(); 

    } 

} 

결과 :

Inside Static Block 
Inside Ananymous Block 
Inside COnstructor of Class 
******************* 
Inside Ananymous Block 
Inside COnstructor of Class 
1
public static final Boolean TRUE = new Boolean(true); 

TRUE 상수는 객체에 대한 참조 포인트가, 최종 사용자가 그것을 변경할 수없는 수단이다 다른 객체를 가리 킵니다. value 상수를 false로 변경 했으므로 이제 개체 값은 false입니다.

관련 문제