hmk run dev

generic 본문

java

generic

hmk run dev 2021. 11. 14. 22:38

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

class Person<T>{
	public T info;
}

public class GenericDemo {
	public static void main(String[] args){
    	Person<String> p1 = new Person<String>(); // p1 & info의 데이터 타입은 string이 된다
		Person<StringBuilder> p2 = new Person<StringBuilder>(); 
    }
}

사용하는 이유

 

아래 코드는 보면  StudentPerson  과 EmployeePerson 은 똑같은 기능을 가지고 있다..

두 개를 대표할 수 있는 클래스를 만들수 있게 해주는 것이 generic

class StudentInfo{
	public int grade;
    StudentInfo(int grade){this.grade = grade}// 생성자
}

class StudentPerson{
	public StudentInfo info;
    StudentPerson(StudentInfo info){this.info = info;}
}

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

class EmployeePerson{
	public EmployeeInfo info;
    EmployeePerson(EmployeeInfo info){this.info = info;} 
}

public class GenericDemo {
	public static void main(String[] args){
    	StudentInfo si = new StudentInfo(2); // 2
        StudentPerson sp = new StudentPerson(si) // si = 2, 
        System.out.println(sp.info.grade); // 2
        EmployeeInfo ei = new EmployeeInfo(1); // 1
        EmployeePerson ep = new EmployeePerson(ei); // 1
        System.out.println(ep.info.rank); // 1
    }
}

 

generic을 사용하지 않았을때 문제

class StudentInfo{
	public int grade;
    StudentInfo(int grade){this.grade = grade}// 생성자
}

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

class Person {
	public Object info; // 자바에서 Object 타입선언은 타입스크립트의 any와 같은 개념인듯..? 아무거나 입력가능
    Person(Object info){ this.info = info; }
}

public class GenericDemo {
	public static void main(String[] args){
    	Person p1 = new Person("부장");
        // Person은 아무타입이나 받을 수 있는 상황
        EmployeeInfo ei = (EmployeeInfo)p1.info; // String 타입의 p1.info를 EmployeeInfo로 형변환 해도 에러메세지가 뜨지 않는다..
        // 컴파일 타이밍에 오류가 검출되고 있지 않다. 실행시켜야 발견
        // 타입이 안전하지 않다고 하는 현상 // 컴파일 언어인 자바의 장점이 없어진다..
        
    }
}

 

generic을 사용한 코드

wrapperClass 참고

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

class Person<T, S>{ // 보통 T부터 관습적으로 많이 쓴다
	// <> 안에 원시타입을 올수 없고 참조형만 올 수 있다. // 원시타입 int, String 등등...
    // 원시타입을 쓰고 싶다면 wrapperClass를 쓰면 된다. ex) int > integer
	public T info;
    public S id;
    Person(T info, S id){
    	this.info = info; // 1
        this.id = id; // 1
    }
}

public class GenericDemo {
	public static void main(String[] args
    	integer id = new Integer(1); // 원시 타입 int 대신 이렇게 wrapperClass를 사용
    	Person<EmployeeInfo, integer> p1 = new Person<EmployeeInfo, integer>(new EmployeeInfo(1), id);
        // T(info)의 위치에 EmployeeInfo, S(id)의 위치에 int
        
        System.out.println(p1.id.intValue()); // wrapperClass가 가지고 있는 int원시 타입으로 가져옴
    }
}

generic 생략

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

class Person<T, S>{ // 보통 T부터 관습적으로 많이 쓴다
	// <> 안에 원시타입을 올수 없고 참조형만 올 수 있다. // 원시타입 int, String 등등...
    // 원시타입을 쓰고 싶다면 wrapperClass를 쓰면 된다. ex) int > integer
	public T info;
    public S id;
    Person(T info, S id){
    	this.info = info; // 1
        this.id = id; // 1
    }
    
    public <U> void printInfo (U info){ // U 인자의 타입을 지정하지 않음
    	System.out.println(info);
    }
}

public class GenericDemo {
	public static void main(String[] args
    	EmployeeInfo e = new EmployeeInfo(1);
    	integer i = new Integer(10); // 원시 타입 int 대신 이렇게 wrapperClass를 사용
    	Person p1 = new Person(e,i); // 제네릭 생략
        
        p1.printInfo(e); // 메소드에 제네릭 적용
    }
}

 

generic 제한 (아무 타입이나 들어올 수 없게제한)

abstract class Info{
	public abstract int getLevel(); //Info를 상속받은 class는 getLevel을 구현해야함
}

interface Info { // 추상 클래스 외에 인터페이스로도 제네릭 제한가능 // 물론 class에 extends대신 implements쓰기!
	int getLevel();
}

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

class Person<T extends Info> { // Info의 자식인지 검사 // interface도 extends 사용해야한다.
	public T info; // 자바에서 Object 타입선언은 타입스크립트의 any와 같은 개념인듯..? 아무거나 입력가능
    Person(T info){ 
    	this.info = info; 
    	info.getLevel(); // 위에 <>안에 extends Info가 있는 경우만 호출가능
    }
}

public class GenericDemo {
	public static void main(String[] args){
    	Person <EmployeeInfo>p1 = new Person<EmployeeInfo>(new EmployeeInfo(1));
        Person<String> p2 = new Person<String>("부장"); // String은 Info의 자식이 아님! 에러!
        
    }
}

 

출처 & 참고

https://www.youtube.com/watch?v=YUinFIexEQ4 

 

'java' 카테고리의 다른 글

추상클래스 & 인터페이스  (0) 2022.02.16
JAVA 메모리 구조  (0) 2022.01.31
JPA @Query 띄워쓰기 주의 사항  (0) 2022.01.12
jsoup 네이버 블로그 크롤링(iframe)  (5) 2021.12.04
interface  (0) 2021.11.14
Comments