JAVA (제네릭)

김민성·2023년 7월 7일

JAVA

목록 보기
11/11

Box라는 클래스를 선언하려고 하고, Box에 넣을 내용물로 content필드를 선언하려고 할 때, 타입을 무엇으로 해야할까?

  • Box는 다양한 내용물을 저장해야 하므로 특정 타입으로 선언할 수 없기 때문에 Object 타입으로 선언
public class Box{
	public Object content;
}
  • Object 클래스는 모든 클래스의 부모 클래스이므로 모든 객체는 부모 타입인 Object로 자동 타입 변환이 되므로 content에는 어떤 객체든 대입이 가능
box Box = new Box();
box.content = 모든 객체;
  • content는 Object 타입이므로 어떤 객체가 대입되어 있는지 불확실
    -> 타입을 안다면 강제 타입 변환을 통해 값 얻을 수 있음
String content = (String)box.content;
  • 타입을 모른다면 instanceof 로 타입을 조사할 수 있지만, 매번 이런 방식으로 확인하기는 불가능

Box를 생성하기 전에 개발자는 어떤 내용물을 저장할 지 알고 있다. 따라서 내용물의 타입을 미리 알려주면 Box는 content에 무엇이 대입되고 읽을 때 어떤 타입으로 제공할지 알게 됨

동적 바인딩
: 컴파일할 때 호출하는 메소드와 실행할 때 호출하는 메소드가 유동적으로 적용되는

  • 실제로 멤버가 참조하는 주소 호출하는 방식(dynamic binding)
  • 자바에선 항상 dynamic binding
  • 객체(객체 생성, not 참조)의 메소드를 불러오려면 Casting 방법 사용
    -> A instanceof B 가 true 일 경우 형 변환 가능
    -> A가 B의 자식이거나 같은 경우 true
    -> A의 참조 데이터 타입과 B의 부모가 같은 경우 false

Generic?

: 결정되지 않은 타입을 파라미터로 처리하고 실제 사용할 때 파라미터를 구체적인 타입으로 대체시키는 기능

public class Box<T>{
	public T content;
}

// Box를 생성할 때 파라미터 T를 타입(String 등)으로 대체
Box<String> box = new Box<String>();
// 아래 코드도 가능
Box<String> box = new Box<>();
  • 타입 파라미터를 대체 하는 타입은 클래스 or 인터페이스
    -> primitive 타입은 타입 파라미터의 대체 타입이 될 수 없음

제네릭 타입

: 결정되지 않은 타입을 파라미터로 가지는 클래스/인터페이스

public class 클래스명<A, B> { }
public interface 인터페이스명<A, B> { }
  • EX
public interface Rentable<T> {
	P rent();
}

// Home class
public class Home {
	public void turnOnLight() {
    	System.out.println("전등을 켭니다.");
    }
}

// HomeAgency class 
// 타입 파라미터를 Home 타입으로 대체했으므로 rent()메소드의 리턴 타입도 반드시 Home 타입이어야 함
public class HomeAgency implements Rentable<Home> {
	@ Override
    public Home rent() {
    	return new Home();
    }
}

// Test
public class Test {
	public static void main(String [] args) {
    	HomeAgency homeagency = new HomeAgency();
        Home home = homeagency.rent();
        home.turnOnLight();
    }
}
-> 전등을 켭니다.

제네릭 메소드

: 타입 파라미터를 가지고 있는 메소드

  • 타입 파라미터가 선언부에 정의됨
public <T, A ...> 리턴타입 메소드명 (매개변수,...) { }
// T타입을 내용물로 갖는 박스 객체 return
public <T> Box<T> boxing(T t) { }

1. Box<Integer> box1 = boxing(100);
2. Box<String> box2 = boxing("안녕하세요");

제한된 타입 파라미터

: 모든 타입으로 대체할 수 없고 특정 타입과 자식 또는 구현 관계에 있는 타입만 대체할 수 있는 타입 파라미터를 '제한된 타입 파라미터'라고 함

  • 숫자를 연산하는 제네릭 메소드는 대체 타입으로 Number / (Byte, Short, Integer, Long, Double)로 제한할 필요가 있음
public <T extends 상위타입> 리턴타입 메소드(매개변수,...) { }
  • 상위 타입은 클래스뿐만 아니라 인터페이스도 가능
    -> 인터페이스라고 implements를 사용하진 않음
  • EX
public <T extends Number> boolean compare(T t1, T t2) {
	double v1 = t1.doubleValue(); // Number의 메소드
    double v2 = t2.doubleValue();
    return (v1 == v2);
}

public static void main(String[] args) {
	boolean result1 = compare(10, 20);
    boolean result2 = compare(4.5, 5.5);

와일드카드 타입 파라미터

: 제네릭 타입을 매개값/리턴타입 으로 사용할 때 타입 파라미터로 ?(와일드카드)를 사용할 수 있음

  • ? 는 범위에 있는 모든 타입으로 대체할 수 있다는 표시

  • Student, HighStudent, MiddleStudent만 타입 파라미터의 대체 타입으로 가능하도록
리턴타입 메소드명 (제네릭타입<? extends Student> 변수) { }
  • Worker, Person만 가능하도록
리턴타입 메소드명 (제네릭타입<? super Worker> 변수) { }
  • 모든 타입 가능하도록
리턴타입 메소드명 (제네릭타입<?> 변수) { }

0개의 댓글