Java 다중 객체 유형 변환 및 동적 바인딩 상세 정보
7532 단어 Java
여기서 말하는 대상 유형 변환은 상속 관계가 있는 대상을 가리키며 임의의 유형의 대상이 아니다.계승 관계가 없는 대상에 대해 강제 형식 변환을 할 때 자바가 실행될 때 자바를 던집니다.lang. ClassCastException 예외입니다.
상속 체인에서 우리는 하위 클래스를 상위 클래스로 전환하는 것을'상향 전환', 하위 클래스를 하위 클래스로 전환하는 것을'하향 전환'이라고 부른다.
많은 경우 우리는 변수를 부류의 유형으로 정의하지만 부류의 대상을 인용한다. 이 과정은 바로 상향 전환이다.프로그램이 실행될 때 동적 연결을 통해 하위 클래스에 대한 호출, 즉 다태성을 실현한다.
그러나 어떤 때는 어떤 부류가 없는 기능을 완성하기 위해 우리는 위로 전환된 하위 대상을 다시 하위 클래스로 바꾸고 하위 클래스를 호출하는 방법이 필요하다. 이것이 바로 아래로 전환하는 것이다.
참고: 상위 클래스의 객체를 직접 하위 클래스 유형으로 강제 변환할 수 없으며 상위 클래스의 하위 클래스 객체만 다시 하위 클래스 유형으로 변환할 수 있습니다.하위 클래스의 대상은 반드시 위로 전환된 후에야 다시 아래로 전환할 수 있다는 것이다.다음 코드를 참조하십시오.
public class Demo {
public static void main(String args[]) {
SuperClass superObj = new SuperClass();
SonClass sonObj = new SonClass();
// ,
// SonClass sonObj2 = (SonClass)superObj;
// ,
superObj = sonObj;
SonClass sonObj1 = (SonClass)superObj;
}
}
class SuperClass{ }
class SonClass extends SuperClass{ }
일곱 번째 줄의 주석을 삭제하면 실행할 때 이상이 발생하지만 컴파일은 통과할 수 있습니다.아래로 전환하는 데 위험이 있기 때문에 부류의 인용을 받을 때 반드시 instanceof 연산자를 사용하여 이 대상이 당신이 원하는 부류인지 판단하십시오. 아래 코드를 보십시오.
public class Demo {
public static void main(String args[]) {
SuperClass superObj = new SuperClass();
SonClass sonObj = new SonClass();
// superObj SonClass
if(superObj instanceof SonClass){
SonClass sonObj1 = (SonClass)superObj;
}else{
System.out.println("① ");
}
superObj = sonObj;
// superObj SonClass
if(superObj instanceof SonClass){
SonClass sonObj2 = (SonClass)superObj;
}else{
System.out.println("② ");
}
}
}
class SuperClass{ }
class SonClass extends SuperClass{ }
실행 결과:
①
요약: 대상의 유형 전환은 프로그램이 실행될 때 검사하고 위로 전환하면 자동으로 진행되며 아래로 전환하는 대상은 현재 인용 유형의 하위 클래스이어야 한다.Java 멀티태스킹 및 동적 바인딩
Java에서 상위 변수는 상위 클래스의 인스턴스를 참조하거나 하위 클래스의 인스턴스를 참조할 수 있습니다.
독자는 먼저 코드를 보십시오.
public class Demo {
public static void main(String[] args){
Animal obj = new Animal();
obj.cry();
obj = new Cat();
obj.cry();
obj = new Dog();
obj.cry();
}
}
class Animal{
//
public void cry(){
System.out.println(" ");
}
}
class Cat extends Animal{
//
public void cry(){
System.out.println(" ~");
}
}
class Dog extends Animal{
//
public void cry(){
System.out.println(" ~");
}
}
실행 결과:
~
~
위의 코드는 세 가지 종류를 정의했는데 그것이 바로 Animal, Cat, Dog이다. Cat과 Dog류는 모두 Animal류에서 계승되었다.obj 변수의 유형은 Animal입니다. 이것은 Animal 클래스의 실례를 가리킬 수도 있고cat와 Dog 클래스의 실례를 가리킬 수도 있습니다. 이것은 정확합니다.즉, 부류의 변수는 부류의 실례를 인용할 수도 있고, 부류의 실례를 인용할 수도 있다.주의는 반대로 잘못된 것이다. 왜냐하면 모든 고양이는 동물이지만, 모든 동물이 고양이는 아니다.이를 통해 알 수 있듯이 obj는 인간일 수도 있고 고양이, 개일 수도 있다. 이것은 서로 다른 표현 형식을 가지고 이를 다태라고 부른다.다태는 한 사물이 서로 다른 표현 형식이나 형태를 가지고 있다는 것을 가리킨다.
그리고'인간'에 대해서도 다양한 표현이나 실현이 있다. TA는 기사, 교사, 의사 등이 될 수 있다. 당신이 자신을 증오할 때'다음 생에 다시 사람이 된다'고 말한다. 그러면 다음 생에 기사, 교사, 의사가 될 수 있다. 우리는'인간'이 다태성을 갖췄다고 말한다.
다태적으로 존재하는 세 가지 필수 조건은 계승, 재작성, 부류 변수 인용 하위 클래스 대상이다.
다중 모드 호출 방법을 사용하는 경우:
먼저 부류에 이 방법이 있는지 확인하고 없으면 컴파일이 잘못됩니다.만약 있다면, 하위 클래스가 이 방법을 덮어썼는지 확인하십시오.
만약 하위 클래스가 이 방법을 덮어쓴다면, 하위 클래스의 방법을 사용하고, 그렇지 않으면 부모 클래스의 방법을 사용합니다.
위의 예에서 알 수 있듯이 다태의 장점 중 하나는 자류가 비교적 많을 때 여러 변수를 정의할 필요도 없고 부류 유형의 변수만 정의하여 서로 다른 자류의 실례를 인용할 수 있다는 것이다.다음 예제를 살펴보십시오.
public class Demo {
public static void main(String[] args){
// ,
Master ma = new Master();
ma.feed(new Animal(), new Food());
ma.feed(new Cat(), new Fish());
ma.feed(new Dog(), new Bone());
}
}
// Animal
class Animal{
public void eat(Food f){
System.out.println(" , " + f.getFood());
}
}
class Cat extends Animal{
public void eat(Food f){
System.out.println(" , " + f.getFood());
}
}
class Dog extends Animal{
public void eat(Food f){
System.out.println(" , " + f.getFood());
}
}
// Food
class Food{
public String getFood(){
return " ";
}
}
class Fish extends Food{
public String getFood(){
return " ";
}
}
class Bone extends Food{
public String getFood(){
return " ";
}
}
// Master
class Master{
public void feed(Animal an, Food f){
an.eat(f);
}
}
실행 결과:
,
,
,
마스터류의feed방법은 두 가지 매개 변수가 있는데 그것이 바로 애니멀류와 푸드류이다. 부류이기 때문에 자류의 실례를 전달할 수 있다. 그러면 마스터류는 여러 가지 방법으로 서로 다른 동물에게 먹이를 줄 필요가 없다.동적 바인딩
다태적 본질을 이해하기 위해 자바 호출 방법의 상세한 절차를 설명합니다.
1) 컴파일러는 객체의 선언 유형과 메서드 이름을 봅니다.
obj를 호출한다고 가정합니다.func(param),obj는 Cat 클래스의 대상입니다.주의해야 할 것은 여러 개의 이름이func일 수 있지만 매개 변수 서명이 다른 방법이 존재할 수 있다는 것이다.예를 들어, func(int) 및 func(String)가 있을 수 있습니다.컴파일러는 모든 Cat 클래스에서func라는 방법과 그 부류 Animal에서 접근 속성이public이고func라는 방법을 일일이 열거할 것입니다.
이렇게 하면 컴파일러는 호출될 수 있는 모든 후보 방법 목록을 얻을 수 있다.
2) 다음에 컴파일러는 호출 방법을 검사할 때 제공하는 인자 서명을 검사합니다.
만약func라는 모든 방법 중 제공된 매개 변수 서명과 완전히 일치하는 방법이 존재한다면 이 방법을 선택하십시오.이 과정은 리셋 해석 (overloading resolution) 이라고 불린다.예를 들어 func ("hello") 를 호출하면 컴파일러는 func (int) 가 아니라 func (String) 를 선택합니다.자동 형식 변환이 존재하기 때문에 예를 들어 int는 더블로 변환할 수 있습니다. 호출 방법 매개 변수와 같은 방법을 찾지 못하면 형식 변환을 한 후에 계속 찾습니다. 최종적으로 일치하는 형식이 없거나 여러 가지 방법이 일치하지 않으면 컴파일이 잘못됩니다.
이렇게 하면 컴파일러는 호출해야 할 방법의 이름과 파라미터 서명을 얻을 수 있다.
3) 방법의 수식자가private,static,final(static,final은 다음에 설명할 것)이거나 구조 방법이라면 컴파일러는 어떤 방법을 사용해야 하는지 정확하게 알 수 있습니다. 우리는 이런 호출 방식을 정적 귀속(static binding)이라고 부릅니다.
이에 대응하는 것은 호출된 방법은 대상의 실제 유형에 의존하고 운행할 때 동적 묶음을 실현한다.예를 들어 func ("hello") 를 호출하면 컴파일러는 동적 귀속 방식으로 func (String) 를 호출하는 명령을 생성합니다.
4) 프로그램이 실행되고 동적 연결 호출 방법을 사용할 때 JVM은 반드시 obj가 인용한 대상의 실제 유형에 가장 적합한 방법을 호출합니다.우리는 이미 obj의 실제 유형이 Cat이라고 가정했다. 이것은 Animal의 하위 클래스이다. 만약에 Cat에서func(String)를 정의하면 그것을 호출한다. 그렇지 않으면 Animal류와 그 상위 클래스에서 찾을 것이다.
매번 호출할 때마다 검색을 해야 하기 때문에 시간 비용이 상당히 많이 들기 때문에 JVM은 모든 방법의 이름, 매개 변수 서명과 소속된 클래스를 열거하는 방법표(method lable)를 미리 만들었습니다.이렇게 되면 진정으로 방법을 호출할 때 가상 머신은 이 시계만 찾으면 된다.위의 예에서 JVM은 func("hello") 호출과 일치하는 방법을 찾기 위해 Cat 클래스의 방법표를 검색합니다.이 방법은 캣일 수도 있어.func(String), Animal일 수도 있습니다.func(String).슈퍼를 호출하면 주의하십시오.func ("hello"), 컴파일러가 부류의 방법표를 튀어나와서 검색합니다.
Animal 클래스에cry(), getName(), getAge() 세 가지 방법이 포함되어 있다고 가정하면 그 방법표는 다음과 같습니다.
cry() -> Animal.cry()
getName() -> Animal.getName()
getAge() -> Animal.getAge()
실제로 Animal도 기본 상위 Object(다음에 설명할 것)가 있고 Object의 방법을 계승하기 때문에 위에서 열거한 방법은 완전하지 않다.
Cat 클래스가 Animal 클래스의 cry () 메서드를 덮어쓰고 climbTree () 메서드를 추가했다고 가정하면 매개변수 목록은 다음과 같습니다.
cry() -> Cat.cry()
getName() -> Animal.getName()
getAge() -> Animal.getAge()
climbTree() -> Cat.climbTree()
실행할 때obj를 호출합니다.cry () 메서드의 절차는 다음과 같습니다.
JVM은 먼저 obj의 실제 유형에 접근하는 방법표입니다. 애니멀 클래스의 방법표일 수도 있고,cat 클래스와 그 하위 클래스의 방법표일 수도 있습니다.
JVM은 메소드 테이블에서cry () 와 일치하는 메소드를 검색하여 찾으면 어떤 종류에 속하는지 알 수 있습니다.
JVM에서 이 메서드를 호출합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.