본문 바로가기

JAVA

JAVA(2022.05.22)-Generic

Generic

- generic이란 데이터 타입을 일반화한다는 것을 의미한다 

- 사용자가 외부에서 필요에 의해 데이터 타입을 지정한다 

- Static 변수는 제네릭을 사용할 수 없다

 

Type

 

타입 설명
<T> Type
<E> Element
<K> Key
<V> Value
<N> Number

 

선언방법

package org.opentutorials.javatutorials.generic;
 
class Person<T>{
    public T info;
}
 
public class GenericDemo {
 
    public static void main(String[] args) {
        Person<String> p1 = new Person<String>();
        Person<StringBuilder> p2 = new Person<StringBuilder>();
    }
 
}

출처: 생활코딩(https://opentutorials.org/course/1223/6237)

 

Person<T>와 publiv T info를 통해 각각의  데이터 타입을 T로 지정하였다

그 후, 인스턴스를 생성할 때

Person<String> p1 = new Person<String>();

Person<StringBuilder> p2 = new Person<StringBuilder>();를 통해 각각의 데이터 타입을 정의해주었다 

 

제네릭화

 

ex)

package org.opentutorials.javatutorials.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);
        StudentPerson sp = new StudentPerson(si);
        System.out.println(sp.info.grade); // 2
        EmployeeInfo ei = new EmployeeInfo(1);
        EmployeePerson ep = new EmployeePerson(ei);
        System.out.println(ep.info.rank); // 1
    }
}

출처 : 생활코딩(https://opentutorials.org/course/1223/6237)

 

위 코드에서 studentPerson과 EmployeePerson은 사실상 같은 구조를 가지고 있기 때문에 중복을 제거해줄 수 있다 

 

>중복을 없앤 코드 

package org.opentutorials.javatutorials.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<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); // 성공
         
        Person<String> p2 = new Person<String>("부장");
        String ei2 = p2.info;
        System.out.println(ei2.rank); // 컴파일 실패
    }
}

출처 : 생활코딩(https://opentutorials.org/course/1223/6237)

 

p1을 생성하며 Person클래스의 타입을<EmployeeInfo>를 통해 지정해주었고

인자로 EmployeeInfo(1)을 넣어주었다 

p2는 컴파일 오류가 발생한다. String 타입을 지정해주었는데, String타입의 필드가 없기 때문이다 

 

 

기본 데이터 타입과 제네릭 

ex)

package org.opentutorials.javatutorials.generic;
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());
    }
}

출처: 생활코딩(https://opentutorials.org/course/1223/6237)]

 

class Person<T, S>처럼 두개의 타입을 지정할 수 있다 

제네릭은 참조 데이터 타입만 사용가능하고, int나 char같은 기본 데이터 타입은 사용이 불가능해서 Wrapper클래스를 사용해줘야한다 

p1인스턴스를 생성하기 전에 

Integer i = new Integer(10);

코드를 통해 p1인스턴스의 매개변수에 i를 넣어 사용할 수 있도록 하였다 

 

 

메소드 Generic

- 제네릭 메소드는 static이 가능하다

 

ex)

package org.opentutorials.javatutorials.generic;
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 <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);
    }
}

출처 : 생활코딩(https://opentutorials.org/course/1223/6237)

 

선언방식은

접근제어자 <제네릭타입> 반환타입 메소드이름(제네릭타입 파라미터)로 선언하면 된다 

 

Generic의 제한 

 

- extends를 통해 제네릭에 올 수 있는 타입을 제한한다 

- 추상클래스를 상속하는 관계에서 뿐만 아니라 Interface를 implements하는 관계에서도 사용이 가능하다 

 

ex) 

package org.opentutorials.javatutorials.generic;
abstract class Info{
    public abstract int getLevel();
}
class EmployeeInfo extends 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>("부장");  //에러발생
        ///String은 info의 자식타입이 아니므로 오류가 발생한다 
    }
}

Person<T extends Info>를 통해 데이터 타입을 Info클래스 자신이나 그 자식으로 제한을 하고 있다 

 

 

 

 

 

 

 

 

*본 게시글은 생활코딩<제네릭>을 공부하며 복습한 내용을 작성한 글입니다*

'JAVA' 카테고리의 다른 글

JAVA(2022.05.24)-java.time패키지  (0) 2022.05.24
JAVA(2022.05.23)-Date,Calendar  (0) 2022.05.23
JAVA(2022.05.21)- Collections Framework  (0) 2022.05.21
JAVA(2022.05.20)-java.util 패키지  (0) 2022.05.20
JAVA(2022.05.19)-스트링 클래스  (0) 2022.05.19