본문 바로가기
JAVA

JAVA instanceof 연산자 [코딩백과 with JAVA]

by GangDev 2024. 12. 21.

instanceof 연산자

instanceof 연산자는 객체가 특정 클래스, 서브클래스, 또는 특정 인터페이스를 구현한 클래스의 인스턴스인지 확인하는 데 사용됩니다. 이는 객체 지향 프로그래밍에서 객체의 타입을 런타임에 확인할 때 매우 유용합니다.

사용 형식:

public class InstanceofExample {
    public static void main(String[] args) {
        Animal animal = new Dog();
        Dog dog = new Dog();
        Cat cat = new Cat();

        System.out.println("animal instanceof Animal: " + (animal instanceof Animal));
        System.out.println("animal instanceof Dog: " + (animal instanceof Dog));
        System.out.println("animal instanceof Cat: " + (animal instanceof Cat));

        System.out.println("dog instanceof Animal: " + (dog instanceof Animal));
        System.out.println("dog instanceof Dog: " + (dog instanceof Dog));
        System.out.println("dog instanceof Cat: " + (dog instanceof Cat));

        System.out.println("cat instanceof Animal: " + (cat instanceof Animal));
        System.out.println("cat instanceof Dog: " + (cat instanceof Dog));
        System.out.println("cat instanceof Cat: " + (cat instanceof Cat));

        // instanceof와 타입 캐스팅
        if (animal instanceof Dog) {
            Dog specificDog = (Dog) animal;
            specificDog.bark();
        }

        // instanceof와 인터페이스
        if (animal instanceof Pet) {
            ((Pet) animal).play();
        }
    }
}

class Animal {}
class Dog extends Animal implements Pet {
    void bark() {
        System.out.println("Woof!");
    }
}

class Cat extends Animal {}

interface Pet {
    void play();
}

이 프로그램의 실행 결과는 다음과 같습니다:

animal instanceof Animal: true
animal instanceof Dog: true
animal instanceof Cat: false
dog instanceof Animal: true
dog instanceof Dog: true
dog instanceof Cat: false
cat instanceof Animal: true
cat instanceof Dog: false
cat instanceof Cat: true
Woof!

주의사항 및 특징

  1. 상속 관계:

    • instanceof는 상속 관계를 고려합니다.
    • 부모 클래스나 인터페이스도 true를 반환합니다.
  2. null 처리:

    • null 객체에 대해 instanceof를 사용하면 항상 false를 반환합니다.
  3. 인터페이스 확인:

    • instanceof는 인터페이스 구현 여부도 확인할 수 있습니다.
  4. 타입 캐스팅:

    • instanceof로 타입을 확인한 후 안전한 타입 캐스팅을 수행할 수 있습니다.
  5. 성능 고려:

    • instanceof는 런타임에 타입을 확인하므로, 과도한 사용은 성능에 영향을 줄 수 있습니다.

사용 예시:

public class InstanceofFeatures {
    public static void main(String[] args) {
        // 상속 관계 확인
        Animal animal = new Dog();
        System.out.println("animal instanceof Animal: " + (animal instanceof Animal));
        System.out.println("animal instanceof Dog: " + (animal instanceof Dog));

        // null 처리
        Object nullObject = null;
        System.out.println("nullObject instanceof Object: " + (nullObject instanceof Object));

        // 인터페이스 구현 확인
        Dog dog = new Dog();
        System.out.println("dog instanceof Pet: " + (dog instanceof Pet));

        // 타입 캐스팅
        Object obj = new Dog();
        if (obj instanceof Dog) {
            Dog specificDog = (Dog) obj;
            specificDog.bark();
        }

        // 성능 고려
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            if (obj instanceof Dog) {}
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Time taken for 10 million instanceof checks: " + (endTime - startTime) + " ms");

        // instanceof와 instanceof의 중첩 사용
        if (obj instanceof Animal && obj instanceof Pet) {
            System.out.println("Object is both Animal and Pet");
        }
    }
}

class Animal {}
class Dog extends Animal implements Pet {
    void bark() {
        System.out.println("Woof!");
    }
}

interface Pet {}

출력 결과는 다음과 같습니다:

animal instanceof Animal: true
animal instanceof Dog: true
nullObject instanceof Object: false
dog instanceof Pet: true
Woof!
Time taken for 10 million instanceof checks: X ms (X는 실행 환경에 따라 다름)
Object is both Animal and Pet

instanceof와 타입 캐스팅

instanceof는 안전한 타입 캐스팅을 위해 자주 사용됩니다:

public class InstanceofCastingExample {
    public static void main(String[] args) {
        Object obj = new Dog();

        // 안전한 타입 캐스팅
        if (obj instanceof Dog) {
            Dog dog = (Dog) obj;
            dog.bark();
        }

        // 인터페이스 타입 캐스팅
        if (obj instanceof Pet) {
            Pet pet = (Pet) obj;
            pet.play();
        }

        // 부모 클래스 타입 캐스팅
        if (obj instanceof Animal) {
            Animal animal = (Animal) animalSound(obj);
        }

        // 안전하지 않은 타입 캐스팅의 위험성
        try {
            Cat cat = (Cat) obj;
            cat.meow();
        } catch (ClassCastException e) {
            System.out.println("ClassCastException occurred: " + e.getMessage());
        }
    }

    private static Animal animalSound(Animal animal) {
        if (animal instanceof Dog) {
            ((Dog) animal).bark();
        } else if (animal instanceof Cat) {
            ((Cat) animal).meow();
        }
        return animal;
    }
}

class Animal {}
class Dog extends Animal implements Pet {
    void bark() {
        System.out.println("Woof!");
    }
}

class Cat extends Animal {
    void meow() {
        System.out.println("Meow!");
    }
}

interface Pet {
    void play();
}

출력 결과는 다음과 같습니다:

Woof!
Woof!
Woof!
ClassCastException occurred: java.lang.ClassCastException: Dog cannot be cast to Cat

instanceof와 인터페이스

instanceof는 인터페이스 구현 여부도 확인할 수 있습니다:

public class InstanceofInterfaceExample {
    public static void main(String[] args) {
        Animal animal = new Dog();
        Object obj = new Cat();

        // 인터페이스 구현 여부 확인
        System.out.println("animal instanceof Pet: " + (animal instanceof Pet));
        System.out.println("obj instanceof Pet: " + (obj instanceof Pet));

        // 인터페이스와 클래스의 조합
        if (animal instanceof Animal && animal instanceof Pet) {
            System.out.println("Animal is both Animal and Pet");
        }

        // 메서드 매개변수 타입 확인
        processAnimal(animal);
        processAnimal(obj);

        // 인터페이스 구현 여부에 따른 동작
        if (animal instanceof Flyable) {
            ((Flyable) animal).fly();
        } else {
            System.out.println("This animal cannot fly");
        }
    }

    private static void processAnimal(Object obj) {
        if (obj instanceof Animal) {
            Animal animal = (Animal) obj;
            animal.makeSound();
        } else {
            System.out.println("Not an Animal");
        }
    }
}

class Animal {
    void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal implements Pet, Flyable {
    @Override
    public void play() {
        System.out.println("Dog is playing");
    }

    @Override
    public void fly() {
        System.out.println("Dog is flying");
    }
}

class Cat extends Animal implements Pet {
    @Override
    public void play() {
        System.out.println("Cat is playing");
    }
}

interface Pet {
    void play();
}

interface Flyable {
    void fly();
}

출력 결과는 다음과 같습니다:

animal instanceof Pet: true
obj instanceof Pet: true
Animal is both Animal and Pet
Animal makes a sound
Not an Animal
This animal cannot fly

instanceof와 상속 계층

instanceof는 상속 계층을 따라 확인합니다:

public class InstanceofHierarchyExample {
    public static void main(String[] args) {
        Vehicle vehicle = new Car();
        Object obj = new Truck();

        // 상속 계층 확인
        System.out.println("vehicle instanceof Car: " + (vehicle instanceof Car));
        System.out.println("vehicle instanceof Vehicle: " + (vehicle instanceof Vehicle));
        System.out.println("vehicle instanceof Object: " + (vehicle instanceof Object));

        // Object 타입으로 선언된 객체의 실제 타입 확인
        System.out.println("obj instanceof Truck: " + (obj instanceof Truck));
        System.out.println("obj instanceof Vehicle: " + (obj instanceof Vehicle));
        System.out.println("obj instanceof Object: " + (obj instanceof Object));

        // 메서드 매개변수 타입 확인
        processVehicle(vehicle);
        processVehicle(obj);

        // 상속 계층에 따른 동작 처리
        if (vehicle instanceof Car) {
            ((Car) vehicle).drive();
        } else if (vehicle instanceof Truck) {
            ((Truck) vehicle).haul();
        } else {
            System.out.println("Unknown vehicle type");
        }
    }

    private static void processVehicle(Object obj) {
        if (obj instanceof Vehicle) {
            Vehicle vehicle = (Vehicle) obj;
            vehicle.move();
        } else {
            System.out.println("Not a Vehicle");
        }
    }
}

class Vehicle {
    void move() {
        System.out.println("Vehicle is moving");
    }
}

class Car extends Vehicle {
    void drive() {
        System.out.println("Car is driving");
    }
}

class Truck extends Vehicle {
    void haul() {
        System.out.println("Truck is hauling");
    }
}
vehicle instanceof Car: true
vehicle instanceof Vehicle: true
vehicle instanceof Object: true
obj instanceof Truck: true
obj instanceof Vehicle: true
obj instanceof Object: true
Vehicle is moving
Vehicle is moving
Car is driving

instanceof 연산자는 Java의 다형성과 객체 지향 프로그래밍의 유연성을 활용할 때 매우 유용합니다. 특히 런타임에 객체의 타입을 확인하고 적절한 처리를 해야 할 때 중요한 역할을 합니다.


편히 모아진 글 보시려면 아래 위키독스 링크 >>
https://wikidocs.net/book/17111