22일차 배운 내용(후,, 쉽지 않다,, 오늘 내용도 이해정도만,, 하는 걸로!!)
1. 제네릭
1) 제네릭 정의 및 사용 이점
2) 제네릭 타입
3) 멀티 타입 파라미터
4) 제너릭 메서드
[ 제네릭 (Generic) ]
[1] 제네릭 정의 및 사용 이점
- 제네릭 정의
: 타입을 파라미터화해서 컴파일 시 구체적인 타입이 결정되도록 하는 것이다.
즉, 데이터의 타입을 일반화한다는 것이다.
클래스나 메서드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법이다.
- 제네릭 사용 이점
public class Apple {
}
public class Box {
private Object object;
public void set(Object object) {
this.object = object;
}
public Object get() {
return object;
}
}
public class BoxExample {
public static void main(String[] args) {
/** 제네릭 타입을 사용하지 않은 경우 **/
Box box = new Box();
box.set("홍길동"); // Object = String <-- 자동형변환
String name = (String)box.get(); // String = (String)Object <-- 강제형변환
box.set(new Apple()); // Object = Apple <-- 자동형변환
Apple apple = (Apple)box.get(); // Apple = (Apple)Object <-- 강제형변환
}
}
[ 위의 코드 : 제네릭을 사용하지 않을 때 ]
// 제네릭 타입 : class<T> 또는 interface<T>
public class Box<T> { // <-- Box라는 제네릭 타입이다.
private T t;
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
}
public class BoxExample {
public static void main(String[] args) {
Box<String> box1 = new Box<String>();
box1.set("Hello");
String str1 = box1.get(); // 강제형변환 안해도 바로 String타입에 대입이 가능하다. --> 제네릭의 이점
Box<Integer> box2 = new Box<Integer>();
box2.set(6); // Integer = int <-- 박싱(boxing)
int value = box2.get(); // int = Integer <-- 언박싱(unboxing)
}
}
// Box 객체에 여러가지 타입의 매개변수들이 들어갈 수 있다.
// 그러고 나서 따로 형변환하지 않아도 바로 들어왔던 타입의 변수에 대입이 된다.
// --> 제네릭의 이점
[ 위의 코드 : 제네릭을 사용할 때 ]
- 컴파일 시 강한 타입 체크를 할 수 있다.
--> 클래스나 메서드 내부에서 사용되는 객체의 타입 안정성을 높일 수 있다.
반환값에 대한 타입 변환 및 타입 검사에 들어가는 노력을 줄일 수 있다.
- 타입 변환(casting)을 제거한다.
--> 프로그램 성능이 향상된다.
[2] 제네릭 타입 (class<T>, interface<T>)
- 제네릭 타입
- 타입을 파라미터로 가지는 클래스와 인터페이스
- 선언 시 클래스 또는 인터페이스 이름 뒤에 < > 를 붙인다.
- < > 사이에는 타입 파라미터를 적어준다.
EX)
public class 클래스명<T> {
.......
}
public interface 인터페이스명<T> {
........
}
1) 제네릭 타입을 사용하지 않을 경우
: Object 타입 사용 -> 빈번한 타입 변환 발생 -> 프로그램 성능 저하
2) 제네릭 타입을 사용한 경우
: 클래스 선언할 때 타입 파라미터 사용
컴파일 시 타입 파라미터가 구체적인 클래스로 변경
[3] 멀티 타입 파라미터 (class<K,V, ....>, interface<T, M, .....>)
- 제네릭 타입은 두개 이상의 타입 파라미터 사용이 가능하다.
public class Car {
}
public class Tv {
}
// 멀티 제네릭 타입 클래스
public class Product<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;
}
}
public class ProductExample {
public static void main(String[] args) {
Product<Tv, String> product1 = new Product<Tv, String>();
// Product<T,M>
// T kind , M model
product1.setKind(new Tv()); // T <- Tv
product1.setModel("스마트TV"); // M <- String
Tv tv = product1.getKind();
String tvModel = product1.getModel();
Product<Car, String> product2 = new Product<>();
product2.setKind(new Car()); // T <- Car
product2.setModel("디젤"); // M <- String
Car car = product2.getKind();
String carModel = product2.getModel();
}
}
[4] 제너릭 메서드 (<T, R> R method( T t ) )
- 매개변수 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드를 말한다.
- 선언하는 방법은 리턴 타입 앞에 <> 기호를 추가하고 타입 파라미터를 기술한 다음,
리턴 타 입과 매개 타입으로 타입 파라미터를 사용하면 된다.
// 제너릭 타입 : 타입을 파라미터로 갖는 클래스 또는 인터페이스
public class Box<T> {
private T t;
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
}
// Util 일반 클래스
public class Util {
// 제너릭 메서드
// boxing : 메서드 이름, T : 매개변수 t 의 타입
// Box<T> : 메서드의 리턴타입, <T> : 제너릭 타입
public static <T> Box<T> boxing(T t) {
Box<T> box = new Box<T>();
box.set(t);
return box; // Box<T> 객체 box
}
}
public class BoxingMethodExample {
public static void main(String[] args) {
// Util에 있는 boxing 메서드는 정적 static 메서드이다.
Box<Integer> box1 = Util.<Integer>boxing(100);
// <T> 리턴타입, boxing(T t)
// t = 100 -> T = integer
//
// <T> Box<T> boxing(T t)메서드의 리턴타입은
int intValue = box1.get(); // unboxing, int = Integer;
//Box<String> box2= Util.<String>boxing("홍길동");
//boxing 앞에 있는 <String>을 생략해서 사용할 수 있다.
Box<String> box2= Util.boxing("홍길동");
String strValue = box2.get();
}
}
[ 제너릭 메서드 예제 1 ]
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public void setKey(K key) { this.key = key; }
public void setValue(V value) { this.value = value; }
public K getKey() { return key; }
public V getValue() { return value; }
}
public class Util {
// 제네릭 메서드
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
boolean keyCompare = p1.getKey().equals(p2.getKey()) ;
boolean valueCompare = p1.getValue().equals(p2.getValue());
return keyCompare && valueCompare; // true && true = true;
// && <-- false 하나만 있어도 false가 된다.
// || <-- true 하나만 있어도 true가 된다.
}
}
// Pair<K,V> : 멀티 제너릭 타입
public class CompareMethodExample {
public static void main(String[] args) {
Pair<Integer, String> p1 = new Pair<>(1, "사과");
Pair<Integer, String> p2 = new Pair<Integer, String>(1, "사과");
// new Pair< > 이 < > 안에를 생략해서 적을 수 있다.
boolean result = Util.<Integer, String>compare(p1, p2);
if(result) {
System.out.println("논리적으로 동등한 객체입니다.");
}else {
System.out.println("논리적으로 동등하지 않는 객체입니다.");
}
Pair<String, String> p3 = new Pair<>("user1", "홍길동");
Pair<String, String> p4 = new Pair<>("user2", "홍길동");
boolean result2 = Util.compare(p3, p4);
// 제네릭 타입 <String, String> 생략해서 사용해도 문제 없다.
if(result2) {
System.out.println("논리적으로 동등한 객체입니다.");
}else {
System.out.println("논리적으로 동등하지 않는 객체입니다.");
}
}
}
[ 제너릭 메서드 예제 2 ]
'kh-정보교육원' 카테고리의 다른 글
25, 26, 27, 28일차_배운 내용(나는야 코생아 응애,,) (2) | 2022.12.09 |
---|---|
23,24일차_배운 내용(여전히 코생아) (2) | 2022.12.06 |
22일차(2)_배운 내용(어김없이 코생아) (0) | 2022.12.04 |
21일_배운 내용(오늘도 코생아) (0) | 2022.12.01 |