2009-07-08 3 views
14

불행히도 저는 약 5 년 동안 Java 코드를 작성하지 않았으며 다음 코드가 어떻게 또는 왜 작동 하는지를 기억하지 못합니다.이중 중괄호와 함께이 생성자 호출은 무엇입니까?

나는 비슷한 예를 우연히 만났고, 이것을 깨뜨렸다. 강조 부분은 주석 아래 부분에 있습니다. 이중 대괄호 안에 블록이 오는 생성자 표기법을 얻지 못합니다. 그리고 불행히도 Java 설명서 나 Google을 사용하여 찾을 수 없습니다 (어떤 단어를 Google에 사용해야합니까?). 이 표기법/구문은 어떻게

  1. 라고 :

    package syntaxtest; 
    
    public class Main { 
    
        public static void main(String[] args) { 
    
         // What kind of notation is this? 
         MyTest tester = new MyTest() {{ 
          setName("John Johnson"); 
         }}; 
    
         System.out.println(tester.getName()); 
        } 
    } 
    
    
    class MyTest { 
        private String name; 
    
        public String getName() { 
         return name; 
        } 
    
        public void setName(String name) { 
         this.name = name; 
        } 
    } 
    

    그래서 여기 내 질문입니까?

  2. 어디에서 설명서를 읽을 수 있습니까?

누군가가 첫 번째 질문에 대한 답을 나에게 제공 할 수 있다면 나 자신이 두 번째 질문에 답할 수 있기를 바랍니다.

분명히 말하면 : 출력이 John Johnson 인 것을 알고 있습니다.)하지만 왜 작동하는지 알 수 없습니다.

+0

과 동일합니다. 그것이 무엇인지 알게되면 그것은 분명합니다. –

+0

나는이 깔끔한 속임수를 얼마 전에 보았다. 그러나 나는 또한 그걸로 물건을 부수기가 쉽다거나 매우 신뢰할만한 것이 아니라는 몇 가지 면책 조항을 보았다. 만약 내가 그것을 사용하려고한다면, 나는 A) 그 코드를 모든 사람에게 설명해야만한다고 설명 할 것이다. 그리고 B) 그 다음에 연구를해야한다. 이 패턴을 사용함에 따른 모든 함의를 이해하십시오. –

+0

빠르고 도움이되는 답장을 보내 주셔서 감사합니다. – klekker

답변

20

이이 double brace initialization로 알려져있다 :

첫 번째 중괄호는 새로운 AnonymousInnerClass을 만들고, 두 번째 은 익명의 내부 클래스가 인스턴스화 될 때 실행되는 인스턴스 초기화 블록 선언합니다. "정적 초기화는" 가 키워드 정적이 앞에 위치 관련 개념이다 - 그것은 인스턴스 범위 클래스의 내에서 선언되기 때문에 초기화 블록의이 유형은 공식적으로 "인스턴스 초기화"라고합니다 블록을 개시하고, 클래스 로더 ( http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.6에서 지정된) 클래스 이니셜 블록 어떤 메소드, 필드 및 최종 변수를 사용할 수 가능을 로딩 완료로하는 즉시 클래스 레벨 실행 브레이스 범위가 포함되어 있지만 중 하나 여야합니다. 생성자 전에 초기화 프로그램이 실행된다는 점에주의하십시오.

익명 하위 클래스가 만들어지기 때문에이 옵션은 최종본이 아닌 클래스에서만 작동합니다.

14

하자 레이아웃 약간 다르게 코드 : 여기에 표시되는 내용

MyTest tester = new MyTest() { 
    { 
    setName("John Johnson"); 
    } 
}; 

이중 중괄호 초기화이라고합니다. 객체가 생성 될 때 실행되는 코드를 포함하는 이니셜 라이저 블록과 함께 클래스 MyTest의 익명 내부 하위 클래스가 있습니다.

일반적으로 이러한 코드를 생성자에 넣지 만 익명 내부 클래스에는 생성자가 없으므로 코드가 실행될 때이를 보장하는 유일한 방법입니다.

이렇게 말하면,이 작업을 수행하는 것은 다소 추한 것입니다. 더 좋은 방법이 있습니다. 그러나, 나는 불변의지도를 만드는 데 일반적으로 다음과 관용구에, 경우에 그것을 자신을 사용합니까 :

, 새로운 맵을 작성을 무시
final Map<String, Integer> textToInt = Collections.unmodifiableMap(new HashMap<String, Integer>() {{ 
    put("one", 1); 
    put("two", 2); 
    // etc 
}}); 

이, 이니셜 블록에 몇 가지 값을 추가, 그리고 그것을 감싸고 수정할 수없는지도에서. 내가 처음 내가 무슨 일이 일어 났는지 실현하기 전에 잠시 동안 그것을 지켜 볼 수밖에 없었습니다 유즈넷에 그것을보고

-5
MyTest tester = new MyTest() {{ 
    setName("John Johnson"); 
}}; 

MyTest tester = new MyTest(); 
tester.setName("John Johnson"); 
+3

그것들은 같지 않습니다. 그들의 결과는 같은 수업이 아닙니다. 하나는 MyTest의 인스턴스를 만듭니다. 다른 하나는 MyTest의 익명 하위 클래스 인스턴스를 만듭니다. equals 메서드가 다음과 같이 보이는 경우 public boolean equals (Object other) { if (other.class! = MyTest.class) {return false; } // 좀 더 확인 ... } 다음과 같은 것으로 간주하지 않습니다. –

+3

@mangst 나는 그들이 "대부분의 목적을 위해 기능성을 갖추었다"고 말 했어야했다고 생각한다; 엔지니어들과 모든 사람들의 성격 - 여기에 약간의 소극적이어야합니다. –