## Java `instanceof` 연산자
`instanceof` 연산자는 Java에서 객체가 특정 클래스의 인스턴스인지, 또는 특정 클래스나 인터페이스를 구현했는지를 확인하는 데 사용됩니다. 이 연산자는 런타임 시에 객체의 실제 타입을 체크하며, 조건식의 결과는 `boolean` 타입으로 반환됩니다. 즉, 해당 객체가 특정 클래스의 인스턴스이면 `true`, 그렇지 않으면 `false`를 반환합니다.
### 기본 문법
`instanceof` 연산자의 기본적인 사용법은 다음과 같습니다:
```java
if (object instanceof ClassName) {
// object가 ClassName 타입의 인스턴스일 때 실행될 코드
}
```
여기서 `object`는 검사할 객체이고, `ClassName`은 검사 대상 클래스 또는 인터페이스입니다.
### 예제 코드
```java
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
public class InstanceofExample {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
System.out.println("dog instanceof Animal: " + (dog instanceof Animal)); // true
System.out.println("dog instanceof Dog: " + (dog instanceof Dog)); // true
System.out.println("dog instanceof Cat: " + (dog instanceof Cat)); // false
System.out.println("cat instanceof Animal: " + (cat instanceof Animal)); // true
System.out.println("cat instanceof Dog: " + (cat instanceof Dog)); // false
System.out.println("cat instanceof Cat: " + (cat instanceof Cat)); // true
}
}
```
위 코드에서 `dog` 객체는 `Dog` 클래스의 인스턴스이고, `cat` 객체는 `Cat` 클래스의 인스턴스입니다. `instanceof` 연산자를 사용하여 객체가 특정 클래스나 그 상위 클래스의 인스턴스인지 확인할 수 있습니다.
### 상속 관계에서의 `instanceof`
`instanceof` 연산자는 상속 관계에서도 사용할 수 있습니다. 예를 들어, `Dog` 클래스가 `Animal` 클래스를 상속받고 있을 때, `Dog` 클래스의 인스턴스는 `Animal` 클래스의 인스턴스이기도 합니다.
```java
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
public class InstanceofExample {
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println("dog instanceof Animal: " + (dog instanceof Animal)); // true
}
}
```
이 예제에서 `Dog` 클래스는 `Animal` 클래스를 상속받으므로, `dog` 객체는 `Animal` 클래스의 인스턴스입니다. 따라서 `dog instanceof Animal`은 `true`를 반환합니다.
### 인터페이스와의 관계
`instanceof` 연산자는 클래스뿐만 아니라 인터페이스에 대해서도 사용할 수 있습니다. 객체가 특정 인터페이스를 구현하는지 확인할 때 유용합니다.
```java
interface Pet {}
class Dog implements Pet {}
class Cat implements Pet {}
public class InstanceofExample {
public static void main(String[] args) {
Pet petDog = new Dog();
Pet petCat = new Cat();
System.out.println("petDog instanceof Pet: " + (petDog instanceof Pet)); // true
System.out.println("petDog instanceof Dog: " + (petDog instanceof Dog)); // true
System.out.println("petDog instanceof Cat: " + (petDog instanceof Cat)); // false
System.out.println("petCat instanceof Pet: " + (petCat instanceof Pet)); // true
System.out.println("petCat instanceof Dog: " + (petCat instanceof Dog)); // false
System.out.println("petCat instanceof Cat: " + (petCat instanceof Cat)); // true
}
}
```
위 코드에서 `Dog`와 `Cat` 클래스는 `Pet` 인터페이스를 구현합니다. 따라서 `petDog`와 `petCat` 객체는 모두 `Pet` 타입으로 간주될 수 있습니다.
### `null` 값과 `instanceof`
`instanceof` 연산자는 `null`에 대해 항상 `false`를 반환합니다. 이는 안전한 타입 체크를 가능하게 합니다.
```java
Dog dog = null;
System.out.println("dog instanceof Dog: " + (dog instanceof Dog)); // false
```
이 경우 `dog` 변수가 `null`이기 때문에 `dog instanceof Dog`는 `false`를 반환합니다.
### 제네릭 타입과 `instanceof`
제네릭 타입을 사용할 때 `instanceof` 연산자를 사용하는 것은 조금 더 복잡할 수 있습니다. 제네릭 타입은 컴파일 시에 타입이 지워지기 때문에, 런타임에는 구체적인 타입 정보를 확인할 수 없습니다. 따라서 제네릭 타입을 `instanceof` 연산자로 직접 검사할 수는 없지만, 와일드카드와 같은 방법을 사용하여 간접적으로 확인할 수 있습니다.
```java
import java.util.ArrayList;
import java.util.List;
public class InstanceofGenericExample {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
System.out.println("stringList instanceof List: " + (stringList instanceof List)); // true
System.out.println("intList instanceof List: " + (intList instanceof List)); // true
// 제네릭 타입을 직접 확인할 수는 없음
// System.out.println("stringList instanceof List<String>: " + (stringList instanceof List<String>)); // 컴파일 오류
}
}
```
위 예제에서 `stringList`와 `intList`는 모두 `List` 타입의 인스턴스이지만, 제네릭 타입 매개변수는 런타임에 존재하지 않기 때문에 `List<String>`이나 `List<Integer>`와 같은 구체적인 타입으로는 확인할 수 없습니다.
### 고급 사용 예제: 다형성과 캐스팅
`instanceof`는 다형성을 사용할 때 유용합니다. 다형성은 객체 지향 프로그래밍의 중요한 개념으로, 상위 클래스 타입의 참조 변수가 하위 클래스 타입의 객체를 참조할 수 있게 합니다. 이를 통해 보다 유연하고 확장 가능한 코드를 작성할 수 있습니다.
```java
class Animal {
public void makeSound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
public void makeSound() {
System.out.println("Woof");
}
public void fetch() {
System.out.println("Dog is fetching");
}
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Meow");
}
}
public class InstanceofPolymorphismExample {
public static void main(String[] args) {
Animal animal = new Dog();
animal.makeSound(); // "Woof"
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.fetch(); // "Dog is fetching"
}
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.makeSound();
} else {
System.out.println("animal is not an instance of Cat");
}
}
}
```
위 예제에서 `animal` 변수는 `Animal` 타입이지만 실제로는 `Dog` 클래스의 인스턴스를 참조하고 있습니다. `instanceof`를 사용하여 `animal`이 `Dog` 클래스의 인스턴스인지 확인한 후, 안전하게 `Dog` 타입으로 캐스팅할 수 있습니다. 반면에 `animal`이 `Cat` 클래스의 인스턴스인지 확인할 때는 `false`가 반환되므로 `Cat` 타입으로 캐스팅되지 않습니다.
### 결론
Java의 `instanceof` 연산자는 객체가 특정 클래스나 인터페이스의 인스턴스인지 확인하는 데 매우 유용한 도구입니다. 이를 통해 런타임 시에 객체의 타입을 안전하게 검사하고 적절한 처리를 할 수 있습니다. 다형성과 캐스팅, 그리고 상속 구조에서의 활용 등 다양한 상황에서 `instanceof` 연산자를 적절히 사용하면 보다 견고하고 유연한 코드를 작성할 수 있습니다.
'게으른 개발자의 끄적거림' 카테고리의 다른 글
Http requestwrapper란? (0) | 2024.06.10 |
---|---|
Java this와 this() 차이점 (1) | 2024.06.04 |
eval() vs new Function() 차이점 (0) | 2024.05.29 |
JavaScript .eval() 함수란? (feat. 쓰면 안되는 이유) (0) | 2024.05.29 |
이클립스 plugin 에러 해결방법 (0) | 2024.05.28 |