이 포스트는 FastCampus에 이 강의를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.
사용법을 알아보기 위해 가정을 하나 해봅시다.
자 여기에 3D 프린터가 있다 칩시다.
3D 프린터는 어떤 입체적인 모양을 뽑는 데 쓰죠? 그 모양을 뽑는 데는 재료가 듭니다.
이 재료가 뭐냐에 따라 다르죠.
일단 제네릭을 안 쓰고 코딩해보겠습니다.
{
"프로젝트 이름" : "3D 프린터",
"제네릭 사용 여부" : false,
"개발 도구" : "IntelliJ 2022.2.4",
"개발 자바 버전" : 18,
}
일단 각 재료에 대한 클래스를 만들어야 합니다.
일단 저는 예시로 플라스틱과 파우더로 하겠습니다.
public class Powder {
public String toString() {
return "재료는 Powder 입니다.";
}
}
public class Plastic {
public String toString() {
return "재료는 Plastic 입니다.";
}
}
그 다음으로는 이 두가지 재료를 사용할 클래스 2개를 만들어야 합니다.
public class ThreeDPrinter1 {
private Powder material;
public Powder getMaterial() {
return material;
}
public void setMaterial(Powder material) {
this.material = material;
}
}
public class ThreeDPrinter2 {
private Plastic material;
public Plastic getMaterial() {
return material;
}
public void setMaterial(Plastic material) {
this.material = material;
}
}
이렇게 하면 클래스도 2개 만들어야 하고, 번거롭습니다.
그래서 선대 개발자분들은 재료 자료형을 직접 넣는 대신 Object 클래스를 이용하였었습니다.
public class ThreeDPrinter3 {
private Object material;
public Object getMaterial() {
return material;
}
public void setMaterial(Object material) {
this.material = material;
}
}
근데 이렇게 하면 또 문제가 발생합니다.
테스트 코드를 적어보겠습니다.
public class ThreeDPrinterTest {
public static void main(String[] args) {
ThreeDPrinter3 test = new ThreeDPrinter3();
Powder powder = new Powder();
test.setMaterial(powder);
// 여기까지만 해도 문제는 없었음
Powder p = test.getMaterial();
// 여기에서 문제 발생.
Powder p2 = (Powder) test.getMaterial();
// 강제로 형변환을 해줘야 문제가 해결됨
}
}
깅제로 형변환도 해줘야 하고, Object도 그닥 좋은 방법은 아닌 것 같습니다.
이제 한번 Generic으로 코딩해보겠습니다.
{
"프로젝트 이름" : "3D 프린터",
"제네릭 사용 여부" : true,
"개발 도구" : "IntelliJ 2022.2.4",
"개발 자바 버전" : 18,
}
제네릭은 클래스명 뒤에 <T>
를 붙여주시고, 자료형을 T로 바꿔주시면 됩니다.
public class GenericPrinter<T> {
public T material;
public T getMaterial() {
return material;
}
public void setMaterial(T material) {
this.material = material;
}
public String toString() {
return material.toString();
}
}
테스트 클래스를 다시 적어보겠습니다.
public class ThreeDPrinterGTest {
public static void main(String[] args) {
GenericPrinter<Powder> GP = new GenericPrinter<>();
Powder pw = new Powder();
GP.setMaterial(pw);
System.out.println(GP.toString());
}
}
오류가 사라진 것을 확인할 수 있었습니다.
<>는 다이아몬드 연산자라고 하는 놈입니다.
다이아몬드 연산자가 나오기 전엔 이렇게 써줘야 했었습니다.
GenericPrinter<Powder> GP = new GenericPrinter<Powder>();
하지만 나온 뒤부터는 이렇게 작성이 가능해졌죠.
GenericPrinter<Powder> GP = new GenericPrinter<>();
T에 아무런 자료형도 넣지 않게 된다면, T는 자동으로 Object 형으로 인식합니다.
그래서 T에서 Object 자료형의 메서드를 사용할 수 있죠.
위 코드들은 전부 제 깃허브에 올라가 있습니다.
제네릭 없는 버전은 noGeneric, 제네릭 쓴 버전은 useGeneric 가셔서 소스 보시면 됩니다.
위처럼 T를 쓰면 어떤 자료형이든 넣을 수 있지만, 도리어 문제가 될 수 있습니다.
그래서 다음 시간에는 자료형을 제한할 수 있는 T extend를 배워보도록 하겠습니다.
수고하셨습니다.