제네릭이란?
제네릭 프로그래밍은 자바에서 타입을 일반화하여 재사용 가능한 코드를 작성하는 기법이다. 제네릭을 사용하면 클래스, 인터페이스, 메서드 등에 대해 특정 타입을 지정하지 않고, 다양한 타입에서 동작하도록 할 수 있다. 이는 코드의 재사용성과 안정성을 높여준다.
제네릭 프로그래밍의 주요 이점
- 타입 안정성 : 컴파일 시 타입을 검사하여 런타임 에러를 줄일 수 있다.
- 코드 재사용성 : 다양한 타입을 처리할 수 있는 일반화된 코드를 작성할 수 있다.
- 유지보수성 : 타입 캐스팅을 줄여 가독성과 유지보수성을 향상시킨다.
package ch01;
public class Plastic {
@Override
public String toString() {
return "재료는 플라스틱 입니다";
}
}
package ch01;
public class Powder {
@Override
public String toString() {
return "재료는 파우더 입니다";
}
}
package ch01;
public class ThreeDPrinter {
Plastic material;
// get,set
public Plastic getMaterial() {
return material;
}
public void setMaterial(Plastic material) {
this.material = material;
}
}
package ch01;
public class ThreeDPrinter2 {
Powder material;
// get,set
public Powder getMaterial() {
return material;
}
public void setMaterial(Powder material) {
this.material = material;
}
}
package ch01;
/**
* 컴파일 시점에 material 데이터 타입으로는
* 모든 클래스가 될 수 있다.
*/
public class ThreeDPrinter3 {
Object material;
// get,set
public Object getMaterial() {
return material;
}
public void setMaterial(Object material) {
this.material = material;
}
}
package ch01;
public class MainTest1 {
public static void main(String[] args) {
ThreeDPrinter dPrinter1 = new ThreeDPrinter();
dPrinter1.setMaterial(new Plastic());
System.out.println(dPrinter1.material.toString());
// 위 ThreeDPrinter 한계는 재료가 플라스틱에 종속 되어있다.
// 하자만 사용자 입장에서 재료를 파우더로 변경한다면
// 코드에 수정이나 새로운 클래스가 필요하다.
System.out.println("--------------------");
ThreeDPrinter2 dPrinter2 = new ThreeDPrinter2();
dPrinter2.setMaterial(new Powder());
System.out.println(dPrinter2.material.toString());
System.out.println("============================");
ThreeDPrinter3 dPrinter3 = new ThreeDPrinter3();
dPrinter3.setMaterial(new Plastic());
System.out.println(dPrinter3.material.toString());
System.out.println("----------------------------");
ThreeDPrinter3 dPrinter3_2 = new ThreeDPrinter3();
dPrinter3_2.setMaterial(new Powder());
System.out.println(dPrinter3_2.material.toString());
Plastic plastic01 = (Plastic)dPrinter3.getMaterial(); // 다운 캐스팅
Powder powder01 = (Powder)dPrinter3.getMaterial(); // 오류나는 코드가 된다.
}
}
package ch02;
public class GenericPrinter<T> {
// T 라는 대체 문자를 사용, E - element, K - key, V - value(사실은 아무 문자나 가능하다)
// 자료형 매개변수(type parameter)
// 이 클래스를 사용하는 시점에서 실제 사용될 자료형이 결정 된다.
private T material; // T 대체 문자형으로 변수를 선언
// get,set
public T getMaterial() {
return material;
}
public void setMaterial(T material) {
this.material = material;
}
// GenericPrinter<T> -- 참조 변수를 sysout(참조변수) --> 나의 멤버 material에 toString() 설계함
@Override
public String toString() {
return material.toString();
}
}
package ch02;
import ch01.Plastic;
import ch01.Powder;
public class MainTest2 {
public static void main(String[] args) {
// 재료 선언
Plastic plastic01 = new Plastic();
Powder powder01 = new Powder();
// 사용하는 시점에 T 대신 어떤 자료형을 사용할지 지정을 하면된다.
GenericPrinter<Plastic> genericPrinter1 = new GenericPrinter<>();
genericPrinter1.setMaterial(plastic01); // 메서드 의존 주입
// 최상위 Object 를 활용할때와 비교
// 형변환 할 필요가 없다 (다운 캐스트)
Plastic returnPlastic = genericPrinter1.getMaterial();
System.out.println(returnPlastic);
// 컴파일 시점에 오류를 알려줘서 안정적인 코드 작업이 진행 된다.
// Powder returnPowder = genericPrinter1.getMaterial(); <-- 오류 발생
} // end of main
}
package ch03;
// 직접 객체를 사용할 수 없게 강제성을 부여 - 추상 클래스
public abstract class Material {
public abstract void doPrinting();
}
package ch03;
/**
* T extends 클래스 문법을 사용하기 위해 설계
*/
public class Plastic extends Material {
@Override
public String toString() {
return "재료는 플라스틱 입니다";
}
@Override
public void doPrinting() {
System.out.println("플라스틱 재료로 출력 합니다.");
}
}
package ch03;
/**
* T extends 클래스 문법을 사용하기 위해 설계
*/
public class Powder extends Material {
@Override
public String toString() {
return "재료는 파우더 입니다";
}
@Override
public void doPrinting() {
System.out.println("파우더 재료로 출력 합니다.");
}
}
package ch03;
/**
*
* @param <T> Material Material 를 상속받은 자식 클래스만 대체 문자에 들어올 수 있다.
*/
public class GenericPrinter<T extends Material> {
private T material;
public T getMaterial() {
return material;
}
public void setMaterial(T material) {
this.material = material;
}
@Override
public String toString() {
return material.toString();
}
}
package ch03;
import ch02.Water;
public class MainTest3 {
public static void main(String[] args) {
// <T extends 클래스> 사용하기
// 상위 클래스의 필요성
// T 자료형은 범위를 제한할 수 없음
// 위 문법 사용해서 상위 클래스에 속한 자료형만 대체 문자 안에 들어올 수 있다.
// ch03 패키지 자료형 사용
GenericPrinter<Powder> genericPrinter1 = new GenericPrinter<>();
genericPrinter1.setMaterial(new Powder());
System.out.println(genericPrinter1.toString());
/////////////////////////////////////////////////
// 컴파일시점에서 부터 오류 발생을 한다.
// GenericPrinter<Water> genericPrinter2 = new GenericPrinter<>();
}
}
728x90
'Java' 카테고리의 다른 글
순수 자바코드로 HttpServer 만들기 (0) | 2024.06.03 |
---|---|
소켓을 활용한 HTTP 통신 (0) | 2024.06.03 |
네트워크 프로토콜 (0) | 2024.05.24 |
1:1 양방향 통신 (채팅 기본 기능 구현) (0) | 2024.05.24 |
1 : 1 양방향 통신 (0) | 2024.05.24 |