본문으로 바로가기

제네릭

category onYouTube/Java 2021. 3. 27. 03:15

"제네릭 (Generic)"

     : 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법

 

  • 인스턴스를 사용할 때 데이터 타입을 확정함
  • 매개변수와 비슷하게 동작함
  • 변수의 데이터 타입과 관련이 있음
class Person<T> {

	public T info;
    
 	Person(T info) { this.info = info; }
}
// 제네릭화 하지 않고 info의 데이터 타입을 Object로 지정하면, info에 어떠한 타입이 들어가도 컴파일 오류가 나지 않음 (타입이 안전하지 않음)


public class GenericDemo {

	public static void main(String[] args) {

		Person<String> p1 = new person<String>();
		Person<StringBuilder> p2 = new person<StringBuilder>();
		// p1, p2의 차이는 각각의 info의 데이터 타입이 String인지 StringBuilder인지의 차이임
	}
}

 

  • 컴파일 단계에서 오류가 검출됨
  • 중복의 제거와 타입 안전성을 동시에 추구함
class StudentInfo {

    public int grade;
    
    StudentInfo(int grade) { this.grade = grade; }
}



class EmployeeInfo{

    public int rank;
    
    EmployeeInfo(int rank) { this.rank = rank; }
}



class Person<T> {

    public T info;
    Person(T info) { this.info = info; }
}



public class GenericDemo {

    public static void main(String[] args) {
    
        Person<EmployeeInfo> p1 = new Person<EmployeeInfo>(new EmployeeInfo(1));
        
        EmployeeInfo ei1 = p1.info;
        System.out.println(ei1.rank); // 1
         
        Person<String> p2 = new Person<String>("부장");
        
        String ei2 = p2.info;
        System.out.println(ei2.rank); // 컴파일 실패
		// p2.info가 String이고 String은 rank 필드가 없는데 이것을 호출하고 있기 때문에 컴파일에 실패함
    }
}

 

  • 제네릭 데이터 타입에는 기본 데이터 타입이 아닌, 참조형 데이터 타입만 올 수 있음
class Person<T, S> {

    public T info;
    public S id;
    
    
    Person(T info, S id){ 

        this.info = info; 
        this.id = id;
    }
}
// 복수의 제네릭



public class GenericDemo {

    public static void main(String[] args) {

        Person<EmployeeInfo, int> p1 = new Person<EmployeeInfo, int>(new EmployeeInfo(1), 1);
		// 제네릭 데이터 타입에는 참조형 데이터 타입만 올 수 있음
    }
}

 

  • "wrapper 클래스" : 자바에서 제공하는 클래스로, 기본 데이터 타입을 참조 데이터 타입으로 변환
  • wrapper 클래스를 사용하면 기본 데이터 타입을 사용할 수 있음
class EmployeeInfo {

    public int rank;
    
    EmployeeInfo(int rank) { this.rank = rank; }
}



class Person<T, S> {

    public T info;
    public S id;
    
    
    Person(T info, S id){ 
    
        this.info = info;
        this.id = id;
    }
}



public class GenericDemo {

    public static void main(String[] args) {
    
        EmployeeInfo e = new EmployeeInfo(1);
        Integer i = new Integer(10);
        Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(e, i);
        
        System.out.println(p1.id.intValue());
    }
}

 

  • intValue( ) : Integer 객체에서 int형 값을 추출
  • 제네릭은 생략이 가능함
EmployeeInfo e = new EmployeeInfo(1);
Integer i = new Integer(10);

Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(e, i);

Person p2 = new Person(e, i);
// 제네릭 생략
class Person<T, S> {

    public T info;
    public S id;
    
    
    Person(T info, S id){ 
    
        this.info = info;
        this.id = id;
    }
    
    
    public <U> void printInfo(U info){
    
        System.out.println(info);
    }
    // 제네릭은 메소드에 적용할 수도 있음
}



public class GenericDemo {

    public static void main(String[] args) {
    
        EmployeeInfo e = new EmployeeInfo(1);
        Integer i = new Integer(10);
        
        Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(e, i);
        
        p1.<EmployeeInfo>printInfo(e);
        p1.printInfo(e);
    }
}

 

  • extends로 제네릭으로 올 수 있는 데이터 타입을, 특정 클래스나 인터페이스의 하위로 제한할 수 있음
class Person<T extends Info> {
// Info의 하위 클래스만 타입으로 받겠다는 뜻임

    public T info;
    
    Person(T info) { this.info = info; }
}



public class GenericDemo {

    public static void main(String[] args) {
    
        Person p1 = new Person(new EmployeeInfo(1));
  
        Person<String> p2 = new Person<String>("부장"); // 에러
		// String은 Info의 하위 클래스가 아니기 때문임
    }
}
interface Info {

    int getLevel();
}



class EmployeeInfo implements Info {

    public int rank;
    
    
    EmployeeInfo(int rank) { this.rank = rank; }
    
    
    public int getLevel() {
    
        return this.rank;
    }
}



class Person<T extends Info> {
// 제네릭 데이터 타입을 특정 인터페이스의 하위로 제한할 수 있음

    public T info;
    
    
    Person(T info) { this.info = info; }
}



public class GenericDemo {

    public static void main(String[] args) {
    
        Person p1 = new Person(new EmployeeInfo(1));
        
        Person<String> p2 = new Person<String>("부장");
    }
}

 

  • super는 상위를 제한
    (extends와 반대)

 

class Person<T> {

	public T info;
    
    
	Person(T info) {
    
		this.info = info;
		info.getLevel(); // 에러
		// <T>는 <T extends Object>와 같기 때문에 toString() 등 Object가 기본으로 제공하는 메소드만 사용할 수 있음 
	}
}

'onYouTube > Java' 카테고리의 다른 글

Collections Framework  (0) 2021.03.27
참조  (0) 2021.03.27
상수와 enum  (0) 2021.03.27
Object 클래스  (0) 2021.03.26
예외  (0) 2021.03.26