제네릭타입을 부모 클래스로 사용할 경우

타입 파라미터는 자식 클래스에도 기술해야 한다.

public class ChildProduct<T, M> extends Product<T, M> { ... }

추가적인 타입 파라미터를 가질 수 있다.

public class ChaildProduct<T, M, C> extends Product<T , M > { ... }


제네릭 인터페이스를 구현할 경우

타입 파라미터는  구현 클래스에도 기술해야 한다.

public class StorageImpl<T> implement Storage<T> { ... }

 


exam

public class 제품<T, M> {
private T 종류;
private M 모델;

public T get종류() { return 종류; }

public void set종류(T 종류) {
this.종류 = 종류;
}

public M get모델() {
return 모델;
}

public void set모델(M 모델) {
this.모델 = 모델;
}
}


class Tv{}



public class 자식제품<K,V,C> extends 제품<K, V> {
private C 회사;

public C get회사() {
return 회사;
}

public void set회사(C 회사) {
this.회사 = 회사;
}
}


public interface 보관소<T> {
public void 추가(T item, int index);

public T get(int index);
}



public class 보관소Impl<T> implements 보관소<T> {

private T[] array;

public 보관소Impl(int capacity) {
this.array = (T[]) (new Object[capacity]);
}

@Override
public void 추가(T item, int index) {
array[index] = item;
}

@Override
public T get(int index) {
return array[index];
}
}



public class 자식제품그리고보관소Example {
public static void main(String[] args) {

자식제품<Tv, String, String> 제품 = new 자식제품<>();

제품.set종류(new Tv());
제품.set모델("스마트티비");
제품.set회사("삼성");


보관소<Tv> 보관소 = new 보관소Impl<>(100);

보관소.추가(new Tv(), 0);
Tv tv = 보관소.get(0);

}
}


'JAVA > JAVA' 카테고리의 다른 글

람다식 기본 문법  (0) 2018.06.09
람다식이란?  (0) 2018.06.09
제네릭(Generic) 와일드카드 타입  (0) 2018.06.09
제네릭(Generic) 메소드  (0) 2018.06.08
제네릭(Generic)이란 ? 제네릭 타입이란?  (0) 2018.06.08

와일드카드(?) 타입이란?

제네릭 타입을 매개변수나 리턴타입으로 사용할 때 타입 파라미터를 제한할 목적

※ 비교

<T extends 상위 또는 인터페이스>는 제네릭 타입과 제네릭 메소드를 선언할 때 제한을 한다.

public static void registerCourse(Course<?> course{

public static void registerCourseStudent(Course<? extends Student> course{

public static void registerCourseWorks(Course<? super Worker> course{



와일드카드 타입의 세가지 형태

제네릭타입<?> :     Unbounded WildCards(제한 없음)

타입 파라미터를 대치하는 구체적인 타입으로 모든 클래스나  인터페이스 타입이 올 수 있다.
public static void registerCourse(Course<?> course{



제네릭타입<? extends 상위타입> :     Upper Bounded Wildcards ( 상위 클래스 제한  )

타입 파라미터를 대치하는 구체적인 타입으로 상위 타입이나 하위 타입만 올 수 있다.

public static void registerCourseStudent(Course<? extends Student> course{


exam )    E -> D -> C -> B -> A          E가 D를 상속  -> D가 C를 상속  ->C가 B를 상속 .....


<? extends C>     라면    c, d, e 를 사용 할 수 있다.


제네릭타입<? super 하위타입> :         Lower Bounded Wildcards ( 하위 클래스 제한 )

타입 파라미터를 대치하는 구체적인 타입으로 하위 타입이나 상위 타입이 올 수 있다.

public static void registerCourseWorks(Course<? super Worker> course{


exam )    E -> D -> C -> B -> A          E가 D를 상속  -> D가 C를 상속  ->C가 B를 상속 .....


<? extends C>     라면    c, b, a 를 사용 할 수 있다.




Exam

수강코스를 만들고   수강 생을   수강코스에 넣는다?

만들 클래스들


수강코스  클래스

public class Course<T> {
private String 수강코스명;
private T[] 수강인원;

//외부에서 수강코스명과 인원수를 결정해서 만들어냄
public Course(String 수강코스명, int capacity) {
this.수강코스명 = 수강코스명;
//T가 결정이 안된상태에서 배열을 생성할수 없다.
//수강인원 = new T[capacity] (x)
수강인원 = (T[]) (new Object[capacity]);
}

public String get수강코스명() { return 수강코스명; }
public T[] get수강인원() { return 수강인원; }

public void add(T t) {
for (int i = 0; i < 수강인원.length; i++) {
if (수강인원[i] == null) {
수강인원[i] = t;
break;
}
}
}
}



Person클래스

public class Person {
public String name;

public Person(String name) {
this.name = name;
}

public String getName() { return name; }

@Override
public String toString() {
return name;
}
}

Student 클래스

public class Student extends Person {

public Student(String name) {
super(name);
}
}

HighStudent 클래스

public class HighStudent extends Student {

public HighStudent(String name) {
super(name);
}
}


Worker 클래스

public class Worker extends Person {
public Worker(String name) {
super(name);
}
}



메인 메서드

public class WildCardExample {
// 수강코스의 코슴이름과 수강중인 사람들을 보여주는 메서드들 * 메서드 타입 파라미터가 다름 *
static void registerCourse(Course<?> course) {
System.out.println("registerCourse()메서드의 [ " + course.get수강코스명() + " ] 수강생: " + Arrays.toString(course.get수강인원()));

}

// Student 상위 타입을 제한
static void registerCourseStudent(Course<? extends Student> course) {
System.out.println("registerCourseStudent()메서드의 [ " + course.get수강코스명() + " ] 수강생: " + Arrays.toString(course.get수강인원()));
}

// Worker 하위 타입을 제한
static void registerCourseWorker(Course<? super Worker> course) {
System.out.println("registerCourseWorker()메서드의 [ " + course.get수강코스명() + " ] 수강생: " + Arrays.toString(course.get수강인원()));
}


public static void main(String[] args) {

Course<Person> personCourse = new Course<Person>("사람이면 가능한 과정", 5);
personCourse.add(new Person("일반인"));
personCourse.add(new Worker("직장인"));
personCourse.add(new Student("학생"));
personCourse.add(new HighStudent("고등학생"));

Course<Worker> workerCourse = new Course<>("직장인 과정", 5);
workerCourse.add(new Worker("직장인"));
workerCourse.add(new Worker("직장인"));
//workerCourse.add(new Student("학생")); 불가능


Course<Student> studentCourse = new Course<>("학생 과정", 5);
studentCourse.add(new HighStudent("고등학생"));
studentCourse.add(new Student("학생"));
//studentCourse.add(new Person("일반인")); 불가능

Course<HighStudent> highStudentCourse = new Course<>("고등학생 과정", 5);
highStudentCourse.add(new HighStudent("고등학생"));
//highStudentCourse.add(new Student("학생")); 불가능

registerCourse(personCourse);
registerCourse(workerCourse);
registerCourse(studentCourse);
registerCourse(highStudentCourse);

//상위 타입을 제한했으므로 하위타입인 highStudentCourse 와 studentCourse 사용가능
// registerCourseStudent(personCourse); 불가능
// registerCourseStudent(workerCourse); 불가능
registerCourseStudent(studentCourse);
registerCourseStudent(highStudentCourse);

//하위 타입을 제한했으므로 상위타입인 PersonCourse 와 workerCourse 사용가능
registerCourseWorker(personCourse);
registerCourseWorker(workerCourse);
// registerCourseWorker(studentCourse); 불가능
// registerCourseWorker(highStudentCourse); 불가능


}
}

실행 결과




'JAVA > JAVA' 카테고리의 다른 글

람다식이란?  (0) 2018.06.09
제네릭(Generic) 타입의 상속과 구현  (0) 2018.06.09
제네릭(Generic) 메소드  (0) 2018.06.08
제네릭(Generic)이란 ? 제네릭 타입이란?  (0) 2018.06.08
Thread 정리..??  (0) 2018.06.08

제네릭(Generic)이란?

타입을 파라미터화해서 컴파일시 구체적인 타입이 결정되도록 하는 것.
자바5부터 새로 추가된 기능이다.
컬렉션, 람다식(함수적 인터페이스), 스트림, NIO에서 널리 사용된다.
제네릭을 모르면 도큐먼트를 해석 할 수 없다.?

ClassArrayList<E>
default Biconsumer<T, U> andThen(biConsumer<? super T, ? super U> afger)

제네릭을 사용함으로서 얻는 이점

컴파일시 강한 타입 체크를 할 수 있다.
        실행시  타입 에러가 나는 것 보다는 컴파일시에 미리 타입을 강하게 체크해서 에러를 사전에 방지.

타입변환을 제거할 수 있다.

 List list = new ArrayList();

list.add("hello");                                                              ->

String str = (String)list.get(0)

 List<String> list = new ArrayList<String>();

list.add("hello");

String str = list.get(0);




제네릭 타입이란

  타입을 파라미터로 가지는 클래스와 인터페이스를 말한다.

선언시 클래스 또는 인터페이스 이름 뒤에 "<>" 부호가 붙는다.
"<>" 사이에는 타입 파라미터가 위치한다.

T = 타입

public class 클래스명<T>{...}
public interface 인터페이스명<T>{...}

타입 파라미터

일반적으로 대문자 알파벳 한문자로 표현한다.   T,  V등등

개발 코드에서는 타입 파라미터 자리에 구체적인 타입을 지정해야 한다.

제네릭 타입을 사용할 경우의 효과

 비제네릭
   Object타입을 사용하므로서 빈번한 타입 변환 발생  - > 성능 저하

public class testBox {
private Object object;
public Object getObject() { return object; }
public void setObject(Object object) { this.object = object; }

public static void main(String[] args) {
testBox box = new testBox();
box.setObject("hello"); //String 타입을 Object 타입으로 자동 타입 변환 후 저장
String str = (String) box.getObject();//Object 타입을 String 타입으로 강제 타입 변환 후 얻음
}
}


제네릭 적용    불필요한 타입변환이 필요 없어짐.         제네릭 타입을 사용할때( 제네릭타입의 객체를 만들때 ?)  T 부분을 원하는 타입을 주면 된다.

public class TestGenericBox<T> {
private T t;
public T getT() { return t; }
public void setT(T t) { this.t = t; }

public static void main(String[] args) {
TestGenericBox<String> stringGecericBox = new TestGenericBox<String>();
stringGecericBox.setT("hello");
String str = stringGecericBox.getT();
}
}


두 개 이상의 타입 파라미터를 사용해서 선언할 수 있다.

class<K, V, ...> {...}
interface<K, V, ...> {...}

public class 두개이상의타입파라미터<T, M> {
private T kind;
private M model;

public T getKind() { return kind; }
public void setKind(T kind) { this.kind = kind; }

public M getModel() { return model; }
public void setModel(M model) { this.model = model; }

}


중복된 타입 파라미터를 생략한 다이아몬드( <>) 연산자

두개이상의타입파라미터<Tv, String> 티비 = new 두개이상의타입파라미터<Tv, String>();

//다이아몬드연산자 적용
두개이상의타입파라미터<Tv, String> 티비 = new 두개이상의타입파라미터<>();


Exam

public static void main(String[] args) {
// 제네릭 을 사용사여 생성시 Tv 타입과 String 타입을 지정후 set, get 실행
두개이상의타입파라미터<Tv, String> product1 = new 두개이상의타입파라미터<>();
produck1.setKind(new Tv());
product1.setModel("스마트 TV");
Tv tv = product1.getKind();
String tvModel = product1.getModel();

// 제네릭 을 사용사여 생성시 Car 타입과 String 타입을 지정후 set, get 실행
두개이상의타입파라미터<Car, String> product2 = new 두개이상의타입파라미터<>();
product2.setKind(new Car());
product2.setModel("리어카");
Car car = product2.getKind();
String carModel = product2.getModel();


'JAVA > JAVA' 카테고리의 다른 글

제네릭(Generic) 타입의 상속과 구현  (0) 2018.06.09
제네릭(Generic) 와일드카드 타입  (0) 2018.06.09
제네릭(Generic) 메소드  (0) 2018.06.08
Thread 정리..??  (0) 2018.06.08
자바 기본 변수  (0) 2018.05.08

+ Recent posts