문제

어제 나는 2 시간의 기술 전화 인터뷰 (내가 통과 한 Woohoo!)를 가졌지 만 Java의 동적 바인딩에 관한 다음 질문을 완전히 머프았다. 그리고 몇 년 전 TA 였을 때 학부생들 에게이 개념을 가르치는 데 사용했기 때문에 두 배의 수수께끼입니다.

여기에 제가 주어진 문제가 있습니다.

/* What is the output of the following program? */

public class Test {

  public boolean equals( Test other ) {
    System.out.println( "Inside of Test.equals" );
    return false;
  }

  public static void main( String [] args ) {
    Object t1 = new Test();
    Object t2 = new Test();
    Test t3 = new Test();
    Object o1 = new Object();

    int count = 0;
    System.out.println( count++ );// prints 0
    t1.equals( t2 ) ;
    System.out.println( count++ );// prints 1
    t1.equals( t3 );
    System.out.println( count++ );// prints 2
    t3.equals( o1 );
    System.out.println( count++ );// prints 3
    t3.equals(t3);
    System.out.println( count++ );// prints 4
    t3.equals(t2);
  }
}

나는 출력이 재정의 내에서 두 개의 개별 인쇄 문일이라고 주장했다. equals() 방법 : at t1.equals(t3) 그리고 t3.equals(t3). 후자의 경우는 충분히 명백하고 이전의 경우에도 t1 유형 객체의 참조가 있으므로 유형 테스트로 인스턴스화되므로 동적 바인딩은 재정의 메소드 형태를 호출해야합니다.

분명히. 내 면접관은 저에게 프로그램을 직접 실행하도록 권장했고, Lo와 보라, 재정의 방법에서 단일 출력이있었습니다. t3.equals(t3).

내 질문은 왜, 왜? 그래도 이미 언급했듯이 t1 유형 객체의 참조입니다 (정적 바인딩은 객체의 호출이 발생합니다. equals() 방법), 동적 결합 ~해야 한다 인스턴스화 된 유형의 참조 유형을 기반으로 가장 구체적인 버전의 메소드를 호출하십시오. 내가 무엇을 놓치고 있습니까?

도움이 되었습니까?

해결책

Java는 과부하 된 방법에 대한 정적 바인딩 및 재정의 방법에 대한 동적 바인딩을 사용합니다. 예에서, 평등 메소드는 과부하가 발생합니다 (object.equals ()와 다른 매개 변수 유형이 있습니다. 참조 컴파일 시간에 입력하십시오.

일부 토론 여기

그것이 평등 방법이라는 사실은 실제로 관련성이 없으며, 인터뷰에서 문제에 대한 답변을 바탕으로 이미 알고있는 과부하 대신 오버로드하는 것이 일반적인 실수입니다.

편집 : 좋은 설명 여기 또한. 이 예제는 대신 매개 변수 유형과 관련된 유사한 문제를 보여 주지만 동일한 문제로 인해 발생합니다.

바인딩이 실제로 동적 인 경우 발신자와 매개 변수가 테스트 인스턴스 인 경우 재정의 메소드가 호출 될 것이라고 생각합니다. 따라서 t3.equals (O1)는 인쇄되지 않은 유일한 경우입니다.

다른 팁

그만큼 equals 의 방법 Test 그것을 무시하지 않습니다 equals 의 방법 java.lang.Object. 매개 변수 유형을보십시오! 그만큼 Test 클래스는 과부하입니다 equals 수락하는 방법으로 Test.

만약 equals 메소드는 재정의하기위한 것이며 @override 주석을 사용해야합니다. 이로 인해 컴파일 오류 가이 일반적인 실수를 지적하게됩니다.

흥미롭게도 Groovy 코드 (클래스 파일로 컴파일 될 수 있음)에서 통화를 제외한 모든 사람은 인쇄 문을 실행합니다. (테스트를 객체와 비교하는 것은 명확하게 테스트를 호출하지 않습니다. 이것은 명시 적으로 동적으로 입력 한 변수가 없기 때문에 특히 관심이 있습니다. 프로그래머가 Groovy가 Java 일을 할 것으로 기대하기 때문에 이것이 유해한 것으로 간주되는 몇 곳에서 읽었습니다.

Java는 매개 변수에서 공동 분산을 지원하지 않으며 반품 유형에서만 지원하지 않습니다.

다시 말해, 재정의 메소드에서의 리턴 유형은 재정의 한 내용의 하위 유형 일 수 있지만, 이는 매개 변수에 해당되지 않습니다.

객체의 Equals에 대한 매개 변수가 객체 인 경우, 하위 클래스에 다른 것과 동등한 것을 넣는 것은 과부하가 발생하지 않으며 재정의 메소드가 아닙니다. 따라서 해당 방법이 호출되는 유일한 상황은 T3의 경우와 같이 매개 변수의 정적 유형이 테스트 될 때입니다.

면접 과정에 행운을 빕니다! 학생들을 가르치는 일반적인 알고/데이터 구조 질문 대신 이러한 유형의 질문을하는 회사에서 인터뷰를 받고 싶습니다.

핵심은 equals () 메소드가 표준을 준수하지 않는다는 사실에 있다고 생각합니다. 객체 객체가 아닌 다른 테스트 객체를 사용하므로 equals () 메소드를 재정의하지 않습니다. 즉, 객체가 객체를 호출하는 동안 테스트 객체가 주어진 경우 특별한 일을하기 위해 실제로 과부하를 한 것만으로도 과부하가 걸렸다는 것을 의미합니다. IDE를 통해 해당 코드를 보면 테스트를위한 두 가지 평등 () 방법이 표시됩니다.

이 방법은 재정의 대신 과부하됩니다. 동등한 객체는 항상 객체를 매개 변수로 취합니다.

BTW, 당신은 Bloch의 효과적인 Java (당신이 소유 해야하는)에 이것에 대한 항목이 있습니다.

일부 메모 동적 바인딩 (DD) 및 정적 결합 ̣̣̣(SB) 검색 후 :

1. 실행 중단: (Ref.1)

  • DB : 런타임에
  • SB : 컴파일러 시간

2. 사용:

  • DB : 재정의
  • SB : 과부하 (정적, 개인, 최종) (Ref.2)

참조:

  1. 사용하는 방법을 선호하는 평균 레졸버를 실행하십시오
  2. 수정 자 정적, 개인 또는 최종으로 메소드를 우선 할 수 없기 때문입니다.
  3. http://javarevisited.blogspot.com/2012/03/what-is-static-and-dynamic-binding-in.html

오버로드 대신 재정의 다른 메소드가 추가되면 런타임에 동적 바인딩 호출을 설명합니다.

/* 다음 프로그램의 출력은 무엇입니까? */

public class DynamicBinding {
    public boolean equals(Test other) {
        System.out.println("Inside of Test.equals");
        return false;
    }

    @Override
    public boolean equals(Object other) {
        System.out.println("Inside @override: this is dynamic binding");
        return false;
    }

    public static void main(String[] args) {
        Object t1 = new Test();
        Object t2 = new Test();
        Test t3 = new Test();
        Object o1 = new Object();

        int count = 0;
        System.out.println(count++);// prints 0
        t1.equals(t2);
        System.out.println(count++);// prints 1
        t1.equals(t3);
        System.out.println(count++);// prints 2
        t3.equals(o1);
        System.out.println(count++);// prints 3
        t3.equals(t3);
        System.out.println(count++);// prints 4
        t3.equals(t2);
    }
}

동적 대 정적 바인딩에 대한 흥미로운 기사를 찾았습니다. 동적 바인딩을 시뮬레이션하기위한 코드가 포함되어 있습니다. 내 코드를 더 읽기 쉽게 만들었습니다.

https://sites.google.com/site/jeffhartkopf/covariance

이 SO 질문도 밀접하게 관련되어 있습니다. Java를 우선적으로 메소드 Quirk와 동일합니다

"왜?" 그것이 Java 언어가 정의되는 방법입니다.

인용 공분산 및 분열에 관한 Wikipedia 기사:

반환 유형 공분산은 Java 프로그래밍 언어 버전 J2SE 5.0에서 구현됩니다. 매개 변수 유형은 메소드를 재정의하려면 정확히 동일해야합니다. 그렇지 않으면 메소드가 병렬 정의로 과부하됩니다.

다른 언어는 다릅니다.

여기에 무시할 개념이 없다는 것은 매우 분명합니다. 메소드 과부하입니다. 그만큼 Object() 객체 클래스의 메소드는 유형 객체의 참조 매개 변수를 가져옵니다. equal() 메소드는 유형 테스트의 참조 매개 변수를 가져옵니다.

나는 온라인에서 온 일부 예제의 확장 된 버전 인 두 가지 예를 통해 이것을 설명하려고 노력할 것입니다.

public class Test {

    public boolean equals(Test other) {
        System.out.println("Inside of Test.equals");
        return false;
    }

    @Override
    public boolean equals(Object other) {
        System.out.println("Inside of Test.equals ot type Object");
        return false;
    }

    public static void main(String[] args) {
        Object t1 = new Test();
        Object t2 = new Test();
        Test t3 = new Test();
        Object o1 = new Object();

        int count = 0;
        System.out.println(count++); // prints 0
        o1.equals(t2);

        System.out.println("\n" + count++); // prints 1
        o1.equals(t3);

        System.out.println("\n" + count++);// prints 2
        t1.equals(t2);

        System.out.println("\n" + count++);// prints 3
        t1.equals(t3);

        System.out.println("\n" + count++);// prints 4
        t3.equals(o1);

        System.out.println("\n" + count++);// prints 5
        t3.equals(t3);

        System.out.println("\n" + count++);// prints 6
        t3.equals(t2);
    }
}

여기서, 카운트 값 0, 1, 2 및 3을 갖는 라인의 경우; 우리는 가지고 있습니다 참조물체 ~을 위한 O1 그리고 T1equals() 방법. 따라서 컴파일 시간에 equals() .의 방법 object.class 파일이 제한됩니다.

그러나 그럼에도 불구하고 참조T1 ~이다 물체, 그것은 있습니다 세형테스트 클래스.
Object t1 = new Test();.
따라서 런타임에서는 호출됩니다 public boolean equals(Object other) 그것은

재정의 메소드

. enter image description here

이제 4와 6의 카운트 값의 경우 다시 간단합니다. T3 가지고 있습니다 참조 그리고 초기화 테스트의 호출입니다 equals() 매개 변수가있는 메소드는 객체 참조 및 an입니다

과부하 된 방법

확인!

다시 한번, 컴파일러가 호출 할 방법을 더 잘 이해하려면 메소드를 클릭하면 Eclipse가 컴파일 시간에 호출 할 것으로 생각되는 유사한 유형의 방법을 강조 표시합니다. 컴파일 타임에 호출되지 않으면 해당 메소드는 메소드 재정의 예입니다.

enter image description here

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top