나는 일반적인 경우에 대한 코드를 가지고 :
public class A {
public String show(A obj) {
return ("A and A");
}
}
public class B extends A {
public String show(B obj) {
return ("B and B");
}
public String show(A obj) {
return ("B and A");
}
}
public class C extends B {
}
public class Test {
public static void main(String[] args) {
A a = new B();
B b = new B();
C c = new C();
System.out.println("1--" + a.show(b));
System.out.println("2--" + a.show(c));
}
}
그 결과는 다음과 같습니다
1--B and A
2--B and A
나는 자바 내림차순에서 우선 순위 체인이 알고 :
this.show(O), super.show(O), this.show((super)O), super.show((super)O)
나의 이해는 다음과 같습니다 :
이 코드에서 :
A a = new B()
업 캐스팅 발생합니다. A는 부모 클래스 참조이며, B는 아이의 부모 클래스의 참조입니다. 코드를 컴파일하고 실행하면, 아이의 부모 클래스 참조는 방법을 선택하는 방법을 결정합니다. 이 경우, show(A)
클래스 B가 선택된다.
부모 클래스 정의에 포함되어야 선택에있어서 다형성 충족해야하는 요구 사항도 있습니다.
누군가가 그 결과에 대한 자세한 설명 표시를 줄 수 있을까요?
당신은 결과를 얻을 이유를 얻기 위해 B and A
컴파일 및 실행 : 두 번이 2 개 부분이 있다는 것을 알 필요가있다.
편집
문을 발생하는 경우 a.show(b)
, 컴파일러는 다음과 같은 기본 단계를 수행합니다
- 메소드가 호출 (되는 객체 봐
a
)와 선언 된 유형을 얻을. 이 유형이다A
. - 클래스
A
와 그 슈퍼 타입의 모든 명명 된 모든 메소드의 목록을 작성show
. 컴파일러는 발견 할 것이다show(A)
. 그것은 어떤 방법 보지 않는B
나C
. - 발견 방법의 목록에서 가장 매개 변수 (일치하는지 하나를 선택
b
) (있는 경우).show(A)
받아b
이 방법이 선택되도록.
같은 일이 당신이 전달하는 두 번째 통화에 발생합니다 c
. 처음 두 단계는 동일하고, 세 번째 단계는 다시 찾을 것 show(A)
하나가 있기 때문에, 또한 매개 변수를 일치합니다 c
. 그래서, 통화의 모두에 대해, 나머지 과정은 동일합니다.
컴파일러가 무엇을 필요로하는지 방법을 파악하면, 그것은 바이트 코드 명령어를 생성합니다 invokevirtual
, 그리고 해결 방법을 넣어 show(A)
(오프닝 이클립스에 표시된대로 전화를해야 하나 .class
) :
invokevirtual org.example.A.show(org.example.A) : java.lang.String [35]
실행 시간
런타임은, 때 결국에 도달 invokevirtual
또한 몇 단계를 수행 할 필요가있다.
- 이다 (그때까지 스택에 이미) 메소드가 호출되는 객체를 가져옵니다
a
. - 실제 봐 런타임 이 객체의 유형입니다. 이후
a = new B()
,이 유형입니다B
. - 에보고
B
하고 방법을 찾아보십시오show(A)
. 이 방법은 이후 발견되는B
재정의 그것. 이 경우이 아니었다 경우, 슈퍼 클래스 (에서 보는 것A
과Object
같은 방법을 찾을 때까지). 단지 고려하는 것이 중요하다show(A)
예를 들어, 그래서 방법을.show(B)
에서는B
고려되지 않습니다. - 런타임은 이제 방법 호출
show(A)
에서을B
을주는String
B and A
결과로.
이에 대한 자세한 내용은 주어진다 을위한 사양invokevirtual
:
확인 된 방법은 서명 다형성 (§2.9)되지 않으면, invokevirtual 명령어는 다음 진행한다.
C는 objectref도의 클래스하자. 실제 방법은 다음 조회 절차에 의해 선택되고 호출 될 :
C는 오버라이드 (§5.4.5)이 해결 방법은 다음 m 호출 될 메소드하는 인스턴스 메소드 m에 대한 선언 및 조회 절차가 종료를 포함하는 경우.
C 수퍼 클래스가있는 경우, 그렇지 않으면, 동일한 조회 절차 C의 직접 수퍼를 사용하여 반복적으로 수행된다; 호출되어야 할 메소드가이 조회 절차의 재귀 호출의 결과이다.
그렇지 않고 AbstractMethodError가 발생합니다.
귀하의 예를 들어, objectref
이다 a
, 그 클래스입니다 B
및 해결 방법은에서이다 invokevirtual
( show(A)
에서 A
)
TL은 : DR은 - 컴파일 시간, 실행 어디에서 호출하는 결정 호출에 어떤 방법을 결정합니다.