제네릭 메서드를 공부하다가
클래스의
<T>
와 제네릭 메서드의<T>
는 다르다
라는 이야기를 블로그에 보게 되었다.
Object o = Fruit.<Integer>staticAndGenericMethodWithDif(1);
public static <S> T staticAndGenericMethodWithDif(T id) {
return id;
}
나는 클래스의 타입변수<T>
와 제네릭 메서드의 타입변수 <S>
가 다른 상황에서
클래스 타입변수의 타입을 반환하려면 어떻게 해야할까...? 라는 고민을 하게 되었다.
왜냐하면 해당 메서드를 호출할 때는 제네릭 메서드의 매개변수 타입을 사용하기 때문이다.
(지금 생각해보면 정말로 멍청한 생각이다...ㅋ 역시 코드를 직접 쳐보고 확인해보는 게 제일 좋은 방법이라는 걸 또 다시 깨닫게 되었다.)
그래서! 제네릭 메서드에 대한 오해를 풀고자! 예시 코드를 작성해보았다.
public class GenericTest {
public static void main(String[] args) {
Fruit<String> stringFruit = new Fruit<>();
String s = stringFruit.notStaticMethod("오직 String만 입력할 수 있습니다.");
System.out.println(s);
System.out.println(s.getClass().getName());
System.out.println("---------------------------------");
String s1 = stringFruit.notStaticAndGenericMethodWithSame("object를 입력합니다. - string 입력");
System.out.println(s1);
System.out.println(s1.getClass().getName());
System.out.println("---------------------------------");
Integer integer = stringFruit.notStaticAndGenericMethodWithSame(1);
System.out.println(integer);
System.out.println(integer.getClass().getName());
System.out.println("---------------------------------");
String s2 = stringFruit.notStaticAndGenericMethodWithDif("오직 String만 입력할 수 있습니다");
System.out.println(s2);
System.out.println(s2.getClass().getName());
System.out.println("---------------------------------");
Integer integer1 = Fruit.<Integer>staticAndGenericMethodWithSame(1);
System.out.println(integer1);
System.out.println(integer1.getClass().getName());
}
}
public class Fruit<T> {
// 1번
public T notStaticMethod(T id) {
return id;
}
// 2번
// 호출 시에 T의 타입을 정할 수가 없다.
// 따라서 컴파일 에러가 발생한다.
public static T staticNotGenericMethod(T id){
return id;
}
//3번
public <T> T notStaticAndGenericMethodWithSame(T id) {
return id;
}
//4번
public <S> T notStaticAndGenericMethodWithDif(T id) {
return id;
}
//5번
// public static <S> T staticAndGenericMethodWithDif(T id) {
// return id;
// }
//6번
//호출 시에 S의 타입을 정할 수가 있다.
public static <S> S staticAndGenericMethodWithSame(S id) {
return id;
}
}
실행결과는 아래와 같습니다.
오직 String만 입력할 수 있습니다.
java.lang.String
---------------------------------
object를 입력합니다. - string 입력
java.lang.String
---------------------------------
1
java.lang.Integer
---------------------------------
오직 String만 입력할 수 있습니다
java.lang.String
---------------------------------
1
java.lang.Integer
```java
public class Fruit<T> {
// 1번
public T notStaticMethod(T id) {
return id;
}
이때는 클래스 타입변수 <T>
타입이 method의 return type, 매개변수의 type이다.
public class Fruit<T> {
// 2번
// 호출 시에 T의 타입을 정할 수가 없다.
// 따라서 컴파일 에러가 발생한다.
public static T staticNotGenericMethod(T id){
return id;
}
}
static이면 인스턴스가 생성되지 않은 상황이다. 따라서 클래스 타입변수의 타입을 알 수 없다.
또한 해당 메서드를 호출할 때 T의 타입을 결정할 수도 없기 때문에
우리는 T의 타입을 알 수가 없다.
public class Fruit<T> {
//3번
public <T> T notStaticAndGenericMethodWithSame(T id) {
return id;
}
}
그럼 3번의 경우도 static이 아니기 때문에 제네릭이 사용가능한데, 굳이 제네릭 메서드를 사용한 이유가 무엇일까?
그렇다!!! 이 포스팅의 처음에 언급했던 그 부분을 내가 놓치고 있었다!
클래스의
<T>
와 제네릭 메서드의<T>
는 다르다
<T>
와 제네릭 메서드의 타입변수<T>
는 기호만 같을 뿐 다른 type이 들어갈 수 있다!!!<T>
에는 Object가 들어갈 수 있다.public class Fruit<T> {
//4번
public <S> T notStaticAndGenericMethodWithDif(T id) {
return id;
}
}
⭐클래스의 <T>
와 제네릭 메서드의 <T>
는 다르다⭐라고 했다‼︎
<S>
이다. 하지만 메서드의 반환 타입은 T
이다. 결국 제네릭인 T는 S와 동일한 거라고 봐야하는 건가?클래스의 <T>
와 제네릭 메서드의 <T>
는 다르다라고 했지
같으면 안 된다!!!!는 아니였다
클래스의 <T>
와 제네릭 메서드의 <T>
는 다르다라는 것을 직관적으로 보여주고 있다.(클래스의 제네릭 타입과 메서드의 제네릭 타입이 다른 것을 눈으로 확인할 수 있다.)
하지만, 꼭 같아야 하는 것은 아니다.
클래스의 제네릭 타입
<T>
와 제네릭 메서드의 제네릭 타입<T>
는 같을 수도 다를 수도 있다.
public class Fruit<T> {
//5번
// public static <S> T staticAndGenericMethodWithDif(T id) {
// return id;
// }
<S>
이다. 하지만 클래스의 타입 변수는 <T>
이다.<T>
는 인스턴스 변수이다. 인스턴스가 생성될 때마다 지정되는 것이기 때문이다.위에 언급한 것처럼 클래스의 제네릭 타입 `<T>
를 모르기 때문에 컴파일 에러가 발생한다.
아래 예시도 마찬가지로 **인스턴스가 생성되지 않았기에 <T>
타입을 정확하게 알지 못한다.
public static <S> T staticAndGenericMethodWithDif(S id) {
return id;
}
public class Fruit<T> {
//6번
//호출 시에 S의 타입을 정할 수가 있다.
public static <S> S staticAndGenericMethodWithSame(S id) {
return id;
}
}
Integer integer2 = Fruit.<Integer>staticAndGenericMethodWithSame(1);
System.out.println(integer2);
System.out.println(integer2.getClass().getName());
System.out.println("---------------------------------");
String string = Fruit.<String>staticAndGenericMethodWithSame("String");
System.out.println(string);
System.out.println(string.getClass().getName());
1
java.lang.Integer
---------------------------------
String
java.lang.String
➡️ 즉, 제네릭 메소드의 generic type은 지역 변수이다.