SuperTypeToken #2 TypeToken(ModelMapper)과 ParameterizedTypeReference(Spring) 차이

2020. 9. 7. 12:00 JAVA/Java

TypeToken (ModelMapper)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package org.modelmapper;
 
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
 
import org.modelmapper.internal.util.Assert;
import org.modelmapper.internal.util.Types;
 
 
public class TypeToken<T> {
  private final Type type;
  private final Class<T> rawType;
 
  @SuppressWarnings("unchecked")
  protected TypeToken() {
    Type superclass = getClass().getGenericSuperclass();
    Assert.isTrue(superclass instanceof ParameterizedType, "%s is not parameterized", superclass);
    type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
    Assert.isTrue(
        !(type instanceof TypeVariable),
        "Cannot construct a TypeToken for a TypeVariable. Try new TypeToken<%s>(getClass()) instead.",
        type);
    rawType = (Class<T>) Types.rawTypeFor(type);
  }
 
}
cs


ParameterizedTypeReferenece (Spring)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package org.springframework.core;
 
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
 
import org.springframework.util.Assert;
 
public abstract class ParameterizedTypeReference<T> {
 
    private final Type type;
 
 
    protected ParameterizedTypeReference() {
        Class<?> parameterizedTypeReferenceSubclass = findParameterizedTypeReferenceSubclass(getClass());
        Type type = parameterizedTypeReferenceSubclass.getGenericSuperclass();
        Assert.isInstanceOf(ParameterizedType.class, type);
        ParameterizedType parameterizedType = (ParameterizedType) type;
        Assert.isTrue(parameterizedType.getActualTypeArguments().length == 1);
        this.type = parameterizedType.getActualTypeArguments()[0];
    }
 
    private static Class<?> findParameterizedTypeReferenceSubclass(Class<?> child) {
        Class<?> parent = child.getSuperclass();
        if (Object.class == parent) {
            throw new IllegalStateException("Expected ParameterizedTypeReference superclass");
        }
        else if (ParameterizedTypeReference.class == parent) {
            return child;
        }
        else {
            return findParameterizedTypeReferenceSubclass(parent);
        }
    }
 
}
 
cs


차이점

  가장 큰 차이점은 TypeToken은 일반 클래스이고, ParameterizedTypeReference는 추상 클래스다. ParameterizedTypeReference는 추상클래스라서 그런지 findParameterizedTypeReferenceSubclass 메소드를 보면 재귀 호출로 최 하위 클래스에 Class클래스를 찾아 getGenericSuperClass 메소드를 호출(14라인)해 Type을 얻는다. 

  반대로 TypeToken에 생성자(19라인)에는 바로 getGenericSuperClass 메소드를 호출해 Type을 가져온다. 큰 차이는 없다. 제외한 코드도 있지만, 여기서 설명한 코드가 주요 핵심 코드이고 그렇게 어렵지 않게 이해할 수 있는 코드다.

뭐 특별히 또 설명할게 없다..

출처 : https://blog.woniper.net/320?category=506090