package ex0729;
public class Ex01 {
public static void main(String[] args) {
Test1<Integer> t = new Test1<>();
t.append(10);
t.append(20);
t.append(30);
// t.append("자바"); // 컴파일 오류
Integer i = t.get(2);
System.out.println(i);
}
}
class Test1<E> {
private Object[] data;
private int count;
public Test1() {
data = new Object[10];
}
public void append(E e) {
if(count >= data.length) {
// ArrayIndexOutOfBoundsException() : unchecked 예외. 배열의 첨자가 초과한 경우 발생
throw new ArrayIndexOutOfBoundsException("요소의 개수를 초과 했습니다.");
}
data[count++] = e;
}
@SuppressWarnings("unchecked") // 부적절한 컴파일러의 경고를 제거하기 위해 사용
public E get(int index) {
if(index >= count) {
throw new ArrayIndexOutOfBoundsException(index);
}
// 제네릭으로 casting 하면 경고가 발생
return (E) data[index];
}
public int getCount() {
return count;
}
}
@SuppressWarnings("unchecked") // 부적절한 컴파일러의 경고를 제거하기 위해 사용
하지만 정확하게 알 때만 사용. 거의 사용하지 않는다!!
<위 코드는 아래와 비교해서 이해할 것!>
package ex0729;
public class Ex02 {
public static void main(String[] args) {
Test2<Integer> t = new Test2<>();
t.append(10);
t.append(20);
t.append(30);
// Integer[] i = t.get(); // 런타임 오류. ClassCastException. 배열은 강제 형변환이 안됨.
// Cast가 필요
Object[] oo = t.get();
for (Object o : oo) {
Integer i = (Integer) o;
System.out.println(i);
}
// 제네릭배열은 의미가 없다.
}
}
class Test2<E> {
private E[] data;
private int count;
@SuppressWarnings("unchecked")
public Test2() {
// 제네릭 배열 메모리 할당
// data = new E[10]; // 컴파일 오류
data = (E[]) new Object[10]; // 제네릭은 Object로 메모리할당을 해야 함.
}
public void append(E e) {
if (count >= data.length) {
throw new ArrayIndexOutOfBoundsException("배열 요소의 개수를 초과 했습니다.");
}
data[count++] = e;
}
public E[] get() {
return data;
}
public int getCount() {
return count;
}
}
위에서는 Object로 배열을 만들어서 생성자에서 배열의 메모리 할당을 해주었는데,
밑에서는 제네릭클래스에서 제네릭 배열을 만들었다.
배열의 선언을 위해 생성자에서 할당하려고 했을 때
data = new E[10]; 은 컴파일 오류가 발생했다. 메모리 할당을 위해서는 Object로 해야 했다. 그래서 배열 메모리 할당 후에 data에 다시 제네릭타입으로 캐스팅하고 넣었다. 여기서 느낌표가 발생해서 다시
@SuppressWarnings("unchecked") 를 넣어줬다.
메인 클래스에서 제네릭타입을 Integer로 해서 객체를 생성한 후 Integer 값들을 3개를 넣었는데 그 배열을 다시 만들으려 했으나
Integer[] i = t.get(); // 런타임 오류. ClassCastException. 배열은 강제 형변환이 안된다.
결국 이 배열을 받기 위해서는 Object로 배열을 생성해서 받아야 했다.
package ex0729;
public class Ex03 {
public static void main(String[] args) {
Test3<Integer> t = new Test3<>();
Integer[] i = {10,20,30};
t.set(i);
Integer[] i2 = t.get();
System.out.println(i2[1]);
}
}
class Test3<E> {
private E[] data;
public void set(E[] data) {
this.data = data;
}
public E[] get() {
return data;
}
}
package ex0729;
public class Ex04 {
public static void main(String[] args) {
Test4<Number> ob1 = new Test4<>();
ob1.set(new Integer(30)); // 타입 매개변수의 상속 관계는 성립
System.out.println(ob1.get());
// Number n = ob1.get();
// Integer i = ob1.get(); // 컴파일 오류
// Integer i = (Integer)ob1.get();
// Number n = new Integer(30); // 업 캐스팅
Test4<Integer> ob2 = new Test4<>();
ob2.set(new Integer(30));
// Test4<Number> ob3 = ob2; // 컴파일 오류. 제네릭은 업캐스팅 불가.
}
}
class Test4<T> {
private T t;
public void set(T t) {
this.t=t;
}
public T get() {
return t;
}
}
제네릭 타입을 Number로 주었기 때문에
Integer i = ob1.get(); 은 컴파일 오류이고 강제적으로 캐스팅을 한 후에는 가능하다.
Integer i = (Integer)ob1.get();
Test4<Number> ob3 = ob2; 제네릭은 업캐스팅이 불가해서 컴파일 오류이다.
제네릭은 컴파일 단계에서 타입 안정성을 위해 지원하므로 기본적으로 다형성을 갖지 않는다.
package ex0729;
public class Ex05 {
public static void main(String[] args) {
Test5<Integer> ob = new Test5<>();
ob.set(30);
// Test5<Number> ob2 = ob; // 컴파일 오류. 상속관계가 아님.
// 제네릭은 같은 데이터 타입만 가능. 훨씬 안정적이다.
// 제네릭 - 와일드 카드
// ? : 모든 클래스나 인터페이스가 가능
// 제네릭 타입에 의존적이지 않는 메소드등을 호출
Test5<?> ob2 = ob;
ob2.print();
// ob2.set(new Integer(30) ); // 컴파일 오류. 자료형이 결정되지 않은 상태이므로
}
}
class Test5<T> {
private T t;
public void set(T t) {
this.t=t;
}
public T get() {
return t;
}
public void print() {
System.out.println(t);
}
}
제네릭에 다형성을 갖도록 만들기 위해 와일드 카드를 사용한다.
제네릭 타입의 클래스를 파라미터로 사용할 때 구체적인 타입이 정해지지 않는 경우에 사용한다.
제네릭타입<?>
- 제한 없다.
- 타입 파라미터를 대치하는 구체적인 타입으로 ?에는 모든 클래스나 인터페이스 타입이 올 수 있다.
Test5<?> ob2 = ob;
ob2.print(); // 제네릭 타입에 의존적이지 않은 메소드는 호출할 수 있지만
ob2.set(); // 이것과 같은 제네릭 타입이 들어가는 메소드는 호출할 수 없다. 컴파일 오류,
'쌍용강북교육센터 > 7월' 카테고리의 다른 글
0729_Ex06~Ex09_system : Java API (0) | 2021.07.29 |
---|---|
0729_ConsoleEx_콘솔 입력 (0) | 2021.07.29 |
0728_Ex11~Ex17_generic : 제네릭 (0) | 2021.07.29 |
0728_Ex01~Ex03_exception : 예외처리 (0) | 2021.07.29 |
0727_패키지 (0) | 2021.07.27 |