안녕하세요! 오늘 우리는 instanceof 연산자에 대해 이야기하고, 그 사용 예를 살펴보고, 그 연산과 관련된 몇 가지 사항을 다룰 것입니다. :) JavaRush의 초기 수준에서 이미 이 연산자를 접했습니다. 왜 필요한지 기억하시나요? 그렇지 않다면 상관없습니다. 함께 기억합시다. 변수 X가 참조하는 객체가 일부 클래스 Y에서 생성되었는지 여부를 확인하려면 instanceof 연산자가 필요합니다. 간단하게 들립니다. 우리가 이 주제로 다시 돌아온 이유는 무엇입니까? 우선, 이제 여러분은 Java의 상속 메커니즘과 기타 OOP 원칙에 대해 잘 알고 있기 때문입니다. 인스턴스오브(instanceof) 에 대한 주제는 훨씬 더 명확해지며 더 고급 사용 사례를 살펴보겠습니다. 가다! 테스트가 참이면 instanceof 연산자가 true를 반환하고, 결과가 거짓이면 false를 반환한다는 것을 기억하실 것입니다. 결과적으로 다양한 유형의 테스트 조건에서 가장 자주 발견됩니다(
if…else
). 더 간단한 예부터 시작해 보겠습니다.
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof Integer);
}
}
콘솔에 무엇이 출력될 것이라고 생각하시나요? 글쎄요, 여기서는 분명합니다 :) 객체 х
는 Integer이므로 결과는 true 입니다 . 콘솔 출력: true 예를 들어 문자열에 속하는지 확인해 보겠습니다.
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof String);// error!
}
}
오류가 발생했습니다. 그리고 주의하세요: 컴파일러는 코드가 실행되기 전에도 이를 발행했습니다! 그는 Integer와 String이 자동으로 서로 변환될 수 없으며 상속 관계가 없다는 것을 즉시 확인했습니다. 따라서 Integer 클래스 객체는 String에서 생성되지 않습니다. 이는 편리하고 이미 프로그램 실행 중에 이상한 오류를 방지하는 데 도움이 되므로 컴파일러가 여기서 우리를 도왔습니다. :) 이제 더 복잡한 예제를 살펴보겠습니다. 상속에 대해 언급했으므로 다음과 같은 소규모 클래스 시스템을 사용해 보겠습니다.
public class Animal {
}
public class Cat extends Animal {
}
public class MaineCoon extends Cat {
}
우리는 일반적인 상황에서 객체가 클래스에 속하는지 확인할 때 instanceof가 어떻게 동작하는지 이미 알고 있습니다. 하지만 여기에 부모-자식 관계를 추가하면 어떻게 될까요? 예를 들어, 다음 검사를 통해 어떤 결과가 나올 것이라고 생각하시나요?
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println(cat instanceof Animal);
System.out.println(cat instanceof MaineCoon);
}
}
출력: true false 대답해야 할 주요 질문은 instanceof가 "클래스를 기반으로 생성된 객체"라는 개념을 정확히 어떻게 해독하는가입니다. 결과적으로 우리는 그것을 얻었 Сat instanceof Animal == true
지만 그러한 공식에서 결함을 찾을 수 있습니다. 이 객체는 왜 Cat
클래스를 기반으로 생성 됩니까 Animal
? 자신의 클래스를 기준으로만 만들어진 것 아닌가요? 대답은 매우 간단하며 이미 알아냈을 수도 있습니다. 객체를 생성할 때 생성자가 호출되고 변수가 초기화되는 순서를 기억하세요. 우리는 클래스 생성자에 관한 기사 에서 이 주제를 이미 다루었습니다 . 다음은 해당 강의의 예입니다.
public class Animal {
String brain = "The initial value of brain in the Animal class";
String heart = "The initial value of heart in the Animal class";
public static int animalCount = 7700000;
public Animal(String brain, String heart) {
System.out.println("The constructor of the Animal base class is being executed");
System.out.println("Have the variables of the Animal class already been initialized?");
System.out.println("The current value of the static variable animalCount = " + animalCount);
System.out.println("Current value of brain in class Animal = " + this.brain);
System.out.println("Current value of heart in class Animal = " + this.heart);
this.brain = brain;
this.heart = heart;
System.out.println("Animal base class constructor completed!");
System.out.println("Current value of brain = " + this.brain);
System.out.println("Current value of heart = " + this.heart);
}
}
class Cat extends Animal {
String tail = "The initial value of tail in the Cat class";
static int catsCount = 37;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
System.out.println("The constructor of the Cat class has started (the Animal constructor has already been executed)");
System.out.println("The current value of the static variable catsCount = " + catsCount);
System.out.println("Current value tail = " + this.tail);
this.tail = tail;
System.out.println("Current value tail = " + this.tail);
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
IDE에서 실행하면 콘솔 출력은 다음과 같습니다: 기본 클래스 Animal의 생성자가 실행 중입니다. Animal 클래스의 변수가 이미 초기화되었습니까? 정적 변수 AnimalCount의 현재 값 = 7700000 Animal 클래스의 두뇌 현재 값 = Animal 클래스의 두뇌 초기 값 Animal 클래스의 심장의 현재 값 = Animal 클래스의 심장 초기 값 기본 Animal 클래스의 생성자 작업을 완료했습니다! Brain의 현재 값 = Brain Heart의 현재 값 = Heart Cat 클래스의 생성자가 작업을 시작했습니다. (Animal 생성자는 이미 실행되었습니다.) 정적 변수의 현재 값 catsCount = 37 tail의 현재 값 = tail의 초기 값 Cat 클래스 tail의 현재 값 = Tail 이제 기억하시나요? :) 기본 클래스 생성자가 있는 경우 객체를 생성할 때 항상 먼저 호출됩니다. Instanceof는 객체가 А
클래스에서 생성 되었는지 여부를 확인하려고 할 때 이 원칙을 따릅니다 Б
. 기본 클래스 생성자가 호출되면 의심의 여지가 없습니다. 두 번째 확인을 사용하면 모든 것이 더 간단해집니다.
System.out.println(cat instanceof MaineCoon);
를 생성할 때 생성자가 MaineCoon
호출되지 않았는데 Cat
, 이는 논리적입니다. 결국 MaineCoon
그는 조상 Cat
이 아니라 후손이다. 그러나 Cat
그것은 템플릿이 아닙니다. 좋아, 이건 분명해 보인다. 이렇게 하면 어떻게 될까요?
public class Main {
public static void main(String[] args) {
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
}
}
흠...이건 좀 더 복잡하네요. 추론해 봅시다. 유형의 변수가 있고 Cat
여기에 유형의 개체를 할당했습니다 MaineCoon
. 그런데 이것이 왜 작동하는 걸까요? 이것이 가능합니까? 할 수 있다. 결국 모든 메인쿤은 고양이입니다. 완전히 명확하지 않다면 기본 유형 확장의 예를 기억하세요.
public class Main {
public static void main(String[] args) {
long x = 1024;
}
}
숫자 1024 는 짧습니다 . 바이트 수가 충분하기 때문에 long 변수 에 쉽게 맞습니다 (중첩 인형의 예를 기억하십니까?). 하위 개체는 항상 조상 변수에 할당될 수 있습니다. 지금은 이것을 기억하고 다음 강의에서 이 과정을 더 자세히 분석하겠습니다. 그렇다면 우리의 예는 무엇을 만들어낼까요?
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
instanceof는 무엇을 검사합니까? 클래스 변수입니까 Cat
아니면 클래스 객체입니까 MaineCoon
? 사실 이 질문에 대한 답은 간단합니다. 연산자의 정의를 다시 읽으면 됩니다. 변수가 참조하는 객체가 X
일부 클래스를 기반으로 생성 되었는지 확인하려면 instanceof 연산자가 필요합니다 Y
. instanceof 연산자는 변수가 아닌 객체의 출처를 확인합니다. 따라서 이 예에서는 두 번 모두 콘솔에 true로 표시됩니다 . 즉, 유형의 개체가 있습니다 MaineCoon
. 당연히 클래스를 기반으로 만들어졌지만 MaineCoon
부모 클래스도 기반으로 만들어 졌습니다 Cat
!
GO TO FULL VERSION