소개
이 랩에서는 Java 에서 객체가 특정 인터페이스를 구현하는지 확인하는 방법을 배우게 됩니다. 런타임 타입 검사를 위한 기본적인 도구인 instanceof 키워드의 사용법을 살펴볼 것입니다.
실습을 통해 instanceof를 사용하여 인터페이스 구현을 확인하고, 여러 인터페이스와 관련된 시나리오를 테스트하며, null 또는 구현하지 않는 객체를 처리하는 경우를 다룰 것입니다. 이 랩은 객체의 실제 타입을 결정하고 인터페이스별 기능을 활용하기 위한 실질적인 기술을 제공할 것입니다.
인터페이스 검사를 위해 instanceof 적용
이 단계에서는 Java 에서 instanceof 키워드를 사용하여 객체가 특정 인터페이스의 인스턴스인지 확인하는 방법을 살펴보겠습니다. 이는 상위 클래스 또는 인터페이스 타입의 변수가 있고, 특히 특정 인터페이스에 특정한 메서드를 호출하려는 경우, 해당 변수가 참조하는 객체의 실제 타입을 결정해야 할 때 흔히 사용되는 작업입니다.
먼저, 간단한 인터페이스와 이를 구현하는 클래스를 정의해 보겠습니다.
WebIDE 편집기를 엽니다.
왼쪽의 파일 탐색기에서
~/project디렉토리에 있는지 확인합니다.Printable.java라는 새 파일을 만듭니다. 파일 탐색기에서 마우스 오른쪽 버튼을 클릭하고 "New File"을 선택한 다음Printable.java를 입력하여 만들 수 있습니다.Printable.java를 열고 다음 코드를 추가합니다.package project; public interface Printable { void print(); }이 코드는
print()메서드 하나를 가진Printable이라는 간단한 인터페이스를 정의합니다.파일을 저장합니다 (Ctrl+S 또는 Cmd+S).
이제 Printable 인터페이스를 구현하는 클래스를 만들어 보겠습니다.
~/project디렉토리에서Document.java라는 새 파일을 만듭니다.Document.java를 열고 다음 코드를 추가합니다.package project; public class Document implements Printable { private String content; public Document(String content) { this.content = content; } @Override public void print() { System.out.println("Printing Document: " + content); } }이
Document클래스는Printable인터페이스를 구현하고print()메서드를 구현합니다.파일을 저장합니다.
마지막으로, 인터페이스와 함께 instanceof를 사용하는 것을 보여주는 main 클래스를 만들어 보겠습니다.
~/project디렉토리에서InterfaceCheck.java라는 새 파일을 만듭니다.InterfaceCheck.java를 열고 다음 코드를 추가합니다.package project; public class InterfaceCheck { public static void main(String[] args) { Object obj1 = new Document("Important Report"); Object obj2 = "Just a String"; // Check if obj1 is an instance of Printable if (obj1 instanceof Printable) { System.out.println("obj1 implements Printable"); Printable p1 = (Printable) obj1; // Cast to Printable p1.print(); // Call the print method } else { System.out.println("obj1 does not implement Printable"); } System.out.println("---"); // Check if obj2 is an instance of Printable if (obj2 instanceof Printable) { System.out.println("obj2 implements Printable"); Printable p2 = (Printable) obj2; // This line would cause a ClassCastException if executed p2.print(); } else { System.out.println("obj2 does not implement Printable"); } } }이 코드에서:
Document객체 (Printable을 구현) 를 참조하는obj1과String객체 (Printable을 구현하지 않음) 를 참조하는obj2라는 두 개의Object변수를 만듭니다.if (obj1 instanceof Printable)을 사용하여obj1이 참조하는 객체가Printable인터페이스의 인스턴스인지 확인합니다.- 그렇다면 메시지를 출력한 다음
(Printable) obj1을 사용하여obj1을Printable타입으로 캐스팅합니다. 캐스팅을 통해Object를Printable로 취급하고 해당print()메서드를 호출할 수 있습니다. obj2에 대해서도 동일한 검사를 수행합니다.String은Printable을 구현하지 않으므로else블록이 실행됩니다.
파일을 저장합니다.
이제 코드를 컴파일하고 실행해 보겠습니다.
WebIDE 하단의 터미널을 엽니다.
~/project디렉토리에 있는지 확인합니다.Java 파일을 컴파일합니다.
javac Printable.java Document.java InterfaceCheck.java오류가 없으면 이 명령은
Printable.class,Document.class및InterfaceCheck.class파일을 생성합니다.InterfaceCheck프로그램을 실행합니다.java InterfaceCheck다음과 유사한 출력을 볼 수 있습니다.
obj1 implements Printable Printing Document: Important Report --- obj2 does not implement Printable이 출력은
instanceof가obj1이Printable을 구현하는 반면obj2는 그렇지 않다는 것을 올바르게 식별했음을 확인합니다. 캐스팅 전에instanceof를 사용하는 것은 런타임에ClassCastException오류를 방지하는 데 매우 중요합니다.
여러 인터페이스로 테스트
이 단계에서는 여러 인터페이스로 작업하여 instanceof에 대한 이해를 확장합니다. Java 에서 단일 클래스는 여러 인터페이스를 구현할 수 있으며, instanceof를 사용하여 각 인터페이스를 확인할 수 있습니다.
먼저, 다른 인터페이스를 정의해 보겠습니다.
WebIDE 편집기를 엽니다.
~/project디렉토리에서Editable.java라는 새 파일을 만듭니다.Editable.java를 열고 다음 코드를 추가합니다.package project; public interface Editable { void edit(String newContent); }이 코드는
edit()메서드 하나를 가진Editable이라는 인터페이스를 정의합니다.파일을 저장합니다.
이제 Document 클래스를 수정하여 Printable과 Editable을 모두 구현하도록 하겠습니다.
~/project디렉토리에서Document.java파일을 엽니다.클래스 선언을 수정하여 두 인터페이스를 모두 구현합니다.
package project; public class Document implements Printable, Editable { private String content; public Document(String content) { this.content = content; } @Override public void print() { System.out.println("Printing Document: " + content); } @Override public void edit(String newContent) { this.content = newContent; System.out.println("Document edited."); } }클래스 선언에
, Editable을 추가하고edit()메서드를 구현했습니다.파일을 저장합니다.
다음으로, main 클래스인 InterfaceCheck.java를 수정하여 두 인터페이스를 모두 테스트해 보겠습니다.
~/project디렉토리에서InterfaceCheck.java파일을 엽니다.기존 코드를 다음 코드로 바꿉니다.
package project; public class InterfaceCheck { public static void main(String[] args) { Object obj1 = new Document("Initial Content"); Object obj2 = "Just a String"; System.out.println("Checking obj1:"); // Check if obj1 is an instance of Printable if (obj1 instanceof Printable) { System.out.println("obj1 implements Printable"); Printable p1 = (Printable) obj1; p1.print(); } else { System.out.println("obj1 does not implement Printable"); } // Check if obj1 is an instance of Editable if (obj1 instanceof Editable) { System.out.println("obj1 implements Editable"); Editable e1 = (Editable) obj1; // Cast to Editable e1.edit("Modified Content"); // Call the edit method // After editing, let's print again to see the change if (obj1 instanceof Printable) { // We know it is, but demonstrating Printable p1_after_edit = (Printable) obj1; p1_after_edit.print(); } } else { System.out.println("obj1 does not implement Editable"); } System.out.println("---"); System.out.println("Checking obj2:"); // Check if obj2 is an instance of Printable if (obj2 instanceof Printable) { System.out.println("obj2 implements Printable"); // Printable p2 = (Printable) obj2; // Would cause ClassCastException // p2.print(); } else { System.out.println("obj2 does not implement Printable"); } // Check if obj2 is an instance of Editable if (obj2 instanceof Editable) { System.out.println("obj2 implements Editable"); // Editable e2 = (Editable) obj2; // Would cause ClassCastException // e2.edit("Some Content"); } else { System.out.println("obj2 does not implement Editable"); } } }이 업데이트된 코드에서는 이제
obj1이Printable과Editable의 인스턴스인지 확인합니다.Document가 둘 다 구현하므로obj1에 대한 두if조건이 모두 true 가 됩니다. 또한Editable로 캐스팅한 후edit()메서드를 호출하는 것을 보여줍니다.obj2(String) 의 경우 두 검사 모두 false 가 됩니다.파일을 저장합니다.
마지막으로, 업데이트된 코드를 컴파일하고 실행합니다.
~/project디렉토리에서 터미널을 엽니다.Java 파일을 다시 컴파일합니다.
javac Printable.java Editable.java Document.java InterfaceCheck.javaInterfaceCheck프로그램을 실행합니다.java InterfaceCheck다음과 유사한 출력을 볼 수 있습니다.
Checking obj1: obj1 implements Printable Printing Document: Initial Content obj1 implements Editable Document edited. Printing Document: Modified Content --- Checking obj2: obj2 does not implement Printable obj2 does not implement Editable이 출력은
instanceof가Document객체 (obj1) 가 두 인터페이스를 모두 구현한다는 것을 올바르게 식별했으며,Printable과Editable에서 모두 메서드를 캐스팅하고 호출할 수 있었음을 보여줍니다.String객체 (obj2) 는 올바르게 아무것도 구현하지 않는다는 것을 보여주었습니다.
Null 및 인터페이스 미구현 객체 처리
이 단계에서는 null 참조와 확인 중인 인터페이스를 구현하지 않는 객체를 처리할 때 instanceof 키워드가 어떻게 동작하는지 살펴보겠습니다. 이러한 경우를 이해하는 것은 견고한 코드를 작성하는 데 중요합니다.
InterfaceCheck.java 파일을 수정하여 null 참조와 Printable 또는 Editable을 구현하지 않는 클래스의 객체를 포함해 보겠습니다.
~/project디렉토리에서InterfaceCheck.java파일을 엽니다.기존 코드를 다음 코드로 바꿉니다.
package project; // Assume Printable and Editable interfaces and Document class are already defined public class InterfaceCheck { public static void main(String[] args) { Object obj1 = new Document("Initial Content"); Object obj2 = "Just a String"; // Does not implement Printable or Editable Object obj3 = null; // A null reference Object obj4 = new Object(); // An object that does not implement Printable or Editable System.out.println("Checking obj1 (Document):"); if (obj1 instanceof Printable) { System.out.println("obj1 implements Printable"); } else { System.out.println("obj1 does not implement Printable"); } if (obj1 instanceof Editable) { System.out.println("obj1 implements Editable"); } else { System.out.println("obj1 does not implement Editable"); } System.out.println("---"); System.out.println("Checking obj2 (String):"); if (obj2 instanceof Printable) { System.out.println("obj2 implements Printable"); } else { System.out.println("obj2 does not implement Printable"); } if (obj2 instanceof Editable) { System.out.println("obj2 implements Editable"); } else { System.out.println("obj2 does not implement Editable"); } System.out.println("---"); System.out.println("Checking obj3 (null):"); if (obj3 instanceof Printable) { System.out.println("obj3 implements Printable"); } else { System.out.println("obj3 does not implement Printable"); } if (obj3 instanceof Editable) { System.out.println("obj3 implements Editable"); } else { System.out.println("obj3 does not implement Editable"); } System.out.println("---"); System.out.println("Checking obj4 (Object):"); if (obj4 instanceof Printable) { System.out.println("obj4 implements Printable"); } else { System.out.println("obj4 does not implement Printable"); } if (obj4 instanceof Editable) { System.out.println("obj4 implements Editable"); } else { System.out.println("obj4 does not implement Editable"); } } }이 업데이트된 코드에서는 두 개의 새로운
Object변수를 추가했습니다.obj3은null로 할당됩니다.obj4는 사용자 정의 인터페이스를 구현하지 않는 기본Object클래스의 새 인스턴스로 할당됩니다.
그런 다음
instanceof를 사용하여 이러한 각 객체를Printable과Editable에 대해 확인합니다.파일을 저장합니다.
이제 업데이트된 코드를 컴파일하고 실행해 보겠습니다.
~/project디렉토리에서 터미널을 엽니다.Java 파일을 컴파일합니다.
InterfaceCheck.java만 수정했으므로 해당 파일만 컴파일할 수 있지만, 세 파일을 모두 컴파일하는 것도 괜찮습니다.javac Printable.java Editable.java Document.java InterfaceCheck.javaInterfaceCheck프로그램을 실행합니다.java InterfaceCheck다음과 유사한 출력을 볼 수 있습니다.
Checking obj1 (Document): obj1 implements Printable obj1 implements Editable --- Checking obj2 (String): obj2 does not implement Printable obj2 does not implement Editable --- Checking obj3 (null): obj3 does not implement Printable obj3 does not implement Editable --- Checking obj4 (Object): obj4 does not implement Printable obj4 does not implement Editableobj3(null참조) 에 대한 출력을 확인합니다. 객체 참조가null인 경우instanceof연산자는 확인 중인 타입에 관계없이false를 반환합니다. 이는instanceof의 핵심 동작이며, 검사를 수행할 때NullPointerException오류를 방지합니다.또한
obj4(일반Object) 에 대한 출력을 확인합니다. 예상대로Object클래스는Printable또는Editable을 구현하지 않으므로instanceof검사는false를 반환합니다.이 단계에서는
instanceof가null참조와 함께 사용해도 안전하며, 지정된 인터페이스를 구현하지 않는 객체를 올바르게 식별한다는 것을 보여줍니다.
요약
이 Lab 에서는 instanceof 키워드를 사용하여 Java 에서 객체가 특정 인터페이스를 구현하는지 확인하는 방법을 배웠습니다. 먼저 간단한 인터페이스 (Printable) 와 이를 구현하는 클래스 (Document) 를 정의하는 것으로 시작했습니다. 그런 다음 instanceof를 사용하여 객체가 Printable 인터페이스의 인스턴스인지 확인하는 방법을 보여주는 main 클래스 (InterfaceCheck) 를 만들었습니다. 이 기본적인 기술은 객체를 안전하게 캐스팅하고 인터페이스별 메서드를 호출하는 데 매우 중요합니다.
또한 여러 인터페이스를 구현하는 객체를 테스트하여 instanceof의 유연성을 더 탐구했으며, null 객체 처리 및 대상 인터페이스를 구현하지 않는 객체와 같은 엣지 케이스도 고려했습니다. 이러한 포괄적인 접근 방식은 다양한 시나리오에서 객체의 인터페이스 구현 상태를 안정적으로 결정하는 방법에 대한 강력한 이해를 보장합니다.



