제네릭 자료형 정의.
자바 제네릭(Generic)은 자바에서 도입된 타입 매개변수화 기능입니다.
제네릭을 사용하면 클래스나 메서드를 정의할 때 타입을 매개변수로 받아서 재사용할 수 있습니다.
이는 코드의 재사용성과 유연성을 높여줍니다.
- 클래스에서 사용하는 변수의 자료형이 여러개 일수 있고, 그 기능(메서드)은 동일한 경우 클래스의 자료형을 특정하지 않고 추후 해당 클래스를 사용할 때 지정 할 수 있도록 선언
- 실제 사용되는 자료형의 변환은 컴파일러에 의해 검증되므로 안정적인 프로그래밍 방식
- 컬렉션 프레임워크에서 많이 사용되고 있음
제네릭 자료형을 사용하는 예시.
술을 만들 때 다양한 재료를 기반으로 만들 수 있습니다.
와인은 포도, 맥주는 맥아를 주된 재료로 만들어 집니다.
이를 코드로 만들어 제네릭타입으로 구현해봅시다.
- 자료형 매개변수 T(type parameter) : 이 클래스를 사용하는 시점에 실제 사용할 자료형을 지정, static 변수는 사용할 수 없음
- GenericAlcohol : 제네릭 자료형
- E : element, K: key, V : value 등 여러 알파벳을 의미에 따라 사용 가능
class Grape {
public String toString() {
return "재료는 포도 입니다.";
}
}
class Malt {
public String toString() {
return "재료는 맥아 입니다.";
}
}
class GenericAlcohol<T> {
private T material;
public T getMaterial() {
return material;
}
public void setMaterial(T material) {
this.material = material;
}
public String toString() {
return material.toString();
}
}
public class AlcoholTest {
public static void main(String[] args) {
GenericAlcohol<Grape> wine = new GenericAlcohol<>();
wine.setMaterial(new Grape());
System.out.println(wine);
GenericAlcohol<Malt> beer = new GenericAlcohol<>();
beer.setMaterial(new Malt());
System.out.println(beer);
}
}
// 재료는 포도 입니다.
// 재료는 맥아 입니다.
만약 제네릭 클래스를 사용하지 않는다면 재료에 따른 알콜 클래스를 따로 만들어 사용해야하고
여러 타입을 대체하기 위해 Object 클래스를 사용한다면 사용할 때마다 항변환을 해줘야 합니다.
제네릭은 이런 번거로움과 타입 안정성을 보장할 수 있습니다.
제네릭을 사용하는 이유.
타입 안정성(Type Safety): 제네릭을 사용하면 컴파일 시간에 타입 체크를 할 수 있으므로, 런타임에서 발생할 수 있는 타입 관련 오류를 사전에 방지할 수 있습니다. 이는 예기치 않은 타입 변환 오류를 방지하고 안정성을 제공합니다.
코드 재사용성: 제네릭을 사용하면 여러 종류의 객체나 데이터 타입에 대해 동일한 로직을 사용할 수 있습니다. 타입을 매개변수화하여 클래스나 메서드를 일반화할 수 있기 때문에, 중복 코드를 줄이고 유지 보수성을 향상시킵니다.
컬렉션 라이브러리의 활용: 자바의 컬렉션 라이브러리(예: ArrayList, HashSet)는 제네릭을 활용하여 구현되어 있습니다. 제네릭을 사용하면 컬렉션에서 다양한 타입의 객체를 안전하게 저장하고 검색할 수 있습니다.
타입 변환 감소: 제네릭을 사용하면 타입 변환을 줄일 수 있습니다. 타입 변환은 실행 시간에 오버헤드를 초래할 수 있으며, 오류 가능성을 높일 수 있습니다. 제네릭을 사용하면 컴파일러가 타입 변환을 자동으로 처리해주므로, 안전하고 간편한 코드 작성이 가능합니다.
요약하자면, 자바 제네릭은 타입 안정성을 제공하고 코드 재사용성을 높여주는 기능입니다. 제네릭을 사용하면 타입 관련 오류를 사전에 방지하고, 중복 코드를 줄이며, 컬렉션과 같은 자료구조를 더 유연하게 활용할 수 있습니다.
<T extends 클래스>.
상위 클래스의 필요성.
- T 자료형의 범위를 제한 할 수 있음
- 상위 클래스에서 선언하거나 정의하는 메서드를 활용할 수 있음
- 상속을 받지 않는 경우 T는 Object로 변환되어 Object 클래스가 기본으로 제공하는 메서드만 사용가능
T extends 를 사용한 프로그래밍.
- GenericAlcohol 에 material 변수의 자료형을 상속받아 구현
- T에 무작위 클래스가 들어갈 수 없게 Material 클래스를 상속받은 클래스로 한정
package june2023.day11.generics;
abstract class Material {
abstract void doPrinting();
}
class Grape extends Material{
public String toString() {
return "재료는 포도 입니다.";
}
@Override
void doPrinting() {
System.out.println("와인의 주된 재료는 포도입니다.");
}
}
class Malt extends Material {
public String toString() {
return "재료는 맥아 입니다.";
}
@Override
void doPrinting() {
System.out.println("맥주의 주된 재료는 맥아입니다.");
}
}
class GenericAlcohol<T extends Material> {
private T material;
public T getMaterial() {
return material;
}
public void setMaterial(T material) {
this.material = material;
}
public String toString() {
return material.toString();
}
public void printing() {
material.doPrinting();
}
}
public class AlcoholTest {
public static void main(String[] args) {
GenericAlcohol<Grape> wine = new GenericAlcohol<>();
wine.setMaterial(new Grape());
wine.printing();
GenericAlcohol<Malt> beer = new GenericAlcohol<>();
beer.setMaterial(new Malt());
beer.printing();
}
}
제네릭 메서드 활용하기.
제네릭 메서드.
- 자료형 매개변수를 메서드의 매개변수나 반환 값으로 가지는 메서드는
- 자료형 매개 변수가 하나 이상인 경우도 있음
- 제네릭 클래스가 아니어도 내부에 제네릭 메서드는 구현하여 사용 할 수 있음
- public <자료형 매개 변수> 반환형 메서드 이름(자료형 매개변수.....) { }
제네릭 메서드의 활용 예.
- 두 점(top, bottom)을 기준으로 사각형을 만들 때 사각형의 너비를 구하는 메서드를 만들어 봅니다.
- 두 점은 정수인 경우도 있고, 실수인 경우도 있으므로 제네릭 타입을 사용하여 구현합니다.
public class Point<T, V> {
T x;
V y;
Point(T x, V y){
this.x = x;
this.y = y;
}
public T getX() {
return x;
}
public V getY() {
return y;
}
}
public class GenericMethod {
public static <T, V> double makeRectangle(Point<T, V> p1, Point<T, V> p2) {
double left = ((Number)p1.getX()).doubleValue();
double right =((Number)p2.getX()).doubleValue();
double top = ((Number)p1.getY()).doubleValue();
double bottom = ((Number)p2.getY()).doubleValue();
double width = right - left;
double height = bottom - top;
return width * height;
}
public static void main(String[] args) {
Point<Integer, Double> p1 = new Point<Integer, Double>(0, 0.0);
Point<Integer, Double> p2 = new Point<>(10, 10.0);
double rect = GenericMethod.<Integer, Double>makeRectangle(p1, p2);
System.out.println("두 점으로 만들어진 사각형의 넓이는 " + rect + "입니다.");
}
}
'BACKEND > JAVA' 카테고리의 다른 글
자바 클래스 - Class 클래스 (0) | 2023.06.11 |
---|---|
인터페이스 여러가지 요소와 인터페이스의 상속 (0) | 2023.06.09 |
인터페이스와 다형성(DAO) 활용하기 (0) | 2023.06.09 |
상속과 추상 클래스, 템플릿 메서드 패턴 (0) | 2023.06.09 |
상속과 메서드 오버라이딩, 가상 메서드 원리 (0) | 2023.06.08 |