Created
March 26, 2011 12:45
-
-
Save ryoasai/888253 to your computer and use it in GitHub Desktop.
Various Java5 type patterns to demonstrate generics reflection API.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static org.junit.Assert.*; | |
import java.lang.reflect.Field; | |
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 java.util.List; | |
import org.junit.Test; | |
class TypePatterns<T> { | |
// JDK1.4までに存在していた型のパターン | |
/** 基本型 */ | |
public int primitiveField; | |
/** 参照型 */ | |
public String objectField; | |
/** 配列型 */ | |
public long[] arrayField; | |
// Java5でサポートされるようになった型のパターン | |
/** 型変数 */ | |
public T typeVariableField; | |
/** パラメーター化型 (型パラメーターが普通のクラスの場合) */ | |
public List<String> parameterizedField; | |
/** パラメーター化型 (型パラメーターが型変数の場合) */ | |
public List<T> typeVariableParameterizedField; | |
/** パラメーター化型 (型パラメーターがワイルドカード型の場合) */ | |
public List<? extends Number> wildcardParameterizedField; | |
/** 総称型配列(要素が型変数の場合) */ | |
public T[] typeVariableArrayField; | |
/** 総称型配列(要素がパラメーター化型の場合) */ | |
public List<String>[] parameterizedComponentArrayField; | |
} | |
public class ReflectionTest { | |
// 総称型を使っていない場合 | |
/** | |
* 基本型フィールドに対するリフレクション情報の取得 | |
*/ | |
@Test | |
public void primitiveField() throws Exception { | |
Field primitiveField = TypePatterns.class.getField("primitiveField"); | |
Class<?> primitiveFieldType = primitiveField.getType(); | |
assertEquals(int.class, primitiveFieldType); | |
assertTrue(primitiveFieldType.isPrimitive()); //基本型 | |
// Generics固有の情報 | |
// Generics化されていない場合はClass自身 | |
assertTrue(primitiveField.getGenericType() == primitiveFieldType); | |
} | |
/** | |
* 参照型フィールドに対するリフレクション情報の取得 | |
*/ | |
@Test | |
public void objectField() throws Exception { | |
Field objectField = TypePatterns.class.getField("objectField"); | |
Class<?> objectFieldType = objectField.getType(); | |
assertEquals(String.class, objectFieldType); | |
// Generics固有の情報 | |
// Generics化されていない場合はClass自身 | |
assertTrue(objectField.getGenericType() == objectFieldType); | |
} | |
/** | |
* 配列型フィールドに対するリフレクション情報の取得 | |
*/ | |
@Test | |
public void arrayField() throws Exception { | |
Field arrayField = TypePatterns.class.getField("arrayField"); | |
Class<?> arrayFieldType = arrayField.getType(); | |
assertEquals(long[].class, arrayFieldType); | |
assertTrue(arrayFieldType.isArray());// 配列型 | |
assertEquals(long.class, arrayFieldType.getComponentType()); //要素型の取得 | |
// Generics固有の情報 | |
// Generics化されていない場合はClass自身 | |
assertTrue(arrayField.getGenericType() == arrayFieldType); | |
} | |
// 総称型を使っている場合 | |
/** | |
* 型変数Tに対するリフレクション情報の取得 | |
*/ | |
@Test | |
public void typeVariableField() throws Exception { | |
// JDK1.4までに存在していたAPIは型消去後の情報のみを返す。 | |
Field typeVariableField = TypePatterns.class.getField("typeVariableField"); | |
Class<?> typeVariableFieldType = typeVariableField.getType(); | |
assertEquals(Object.class, typeVariableFieldType); // 型消去後のTの具象化型 | |
// Java5の拡張APIを使いGenerics固有の情報を取得 | |
assertTrue(typeVariableField.getGenericType() instanceof TypeVariable); | |
TypeVariable<?> typeVariable = (TypeVariable<?>)typeVariableField.getGenericType(); | |
assertEquals("T", typeVariable.getName()); // 型変数名「T」 | |
assertArrayEquals(new Type[]{Object.class}, typeVariable.getBounds()); // Tの上限(指定されていないためObject) | |
assertEquals(TypePatterns.class, typeVariable.getGenericDeclaration()); // Tの宣言はTypePatternsクラス | |
} | |
/** | |
* パラメーター化型List<String>に対するリフレクション情報の取得 | |
*/ | |
@Test | |
public void parameterizedField() throws Exception { | |
// JDK1.4までに存在していたAPIは型消去後の情報のみを返す。 | |
Field parameterizedField = TypePatterns.class.getField("parameterizedField"); | |
Class<?> parameterizedFieldType = parameterizedField.getType(); | |
assertEquals(List.class, parameterizedFieldType); // 型消去後のList<String>の具象化型 | |
// Java5の拡張APIを使いGenerics固有の情報を取得 | |
assertTrue(parameterizedField.getGenericType() instanceof ParameterizedType); | |
ParameterizedType parameterizedType = (ParameterizedType)parameterizedField.getGenericType(); | |
assertArrayEquals(new Type[]{String.class}, parameterizedType.getActualTypeArguments()); // 型変数に対するパラメーター値「String」 | |
assertEquals(List.class, parameterizedType.getRawType()); | |
} | |
/** | |
* パラメーター化型List<T>に対するリフレクション情報の取得 | |
*/ | |
@Test | |
public void typeVariableParameterizedField() throws Exception { | |
// JDK1.4までに存在していたAPIは型消去後の情報のみを返す。 | |
Field typeVariableParameterizedField = TypePatterns.class.getField("typeVariableParameterizedField"); | |
Class<?> typeVariableParameterizedFieldType = typeVariableParameterizedField.getType(); | |
assertEquals(List.class, typeVariableParameterizedFieldType); // 型消去後のList<T>の具象化型 | |
// Java5の拡張APIを使いGenerics固有の情報を取得 | |
assertTrue(typeVariableParameterizedField.getGenericType() instanceof ParameterizedType); | |
ParameterizedType parameterizedType = (ParameterizedType)typeVariableParameterizedField.getGenericType(); | |
assertEquals(1, parameterizedType.getActualTypeArguments().length); | |
assertTrue(parameterizedType.getActualTypeArguments()[0] instanceof TypeVariable); | |
TypeVariable<?> typeVariable = (TypeVariable<?>)parameterizedType.getActualTypeArguments()[0]; | |
assertEquals("T", typeVariable.getName()); // 型変数名「T」 | |
assertArrayEquals(new Type[]{Object.class}, typeVariable.getBounds()); // Tの上限(指定されていないためObject) | |
assertEquals(TypePatterns.class, typeVariable.getGenericDeclaration()); // Tの宣言はTypePatternsクラス | |
assertEquals(List.class, parameterizedType.getRawType()); | |
} | |
/** | |
* パラメーター化型<? extends Number>に対するリフレクション情報の取得 | |
*/ | |
@Test | |
public void wildcardParameterizedField() throws Exception { | |
// JDK1.4までに存在していたAPIは型消去後の情報のみを返す。 | |
Field wildcardParameterizedField = TypePatterns.class.getField("wildcardParameterizedField"); | |
Class<?> wildcardParameterizedFieldType = wildcardParameterizedField.getType(); | |
assertEquals(List.class, wildcardParameterizedFieldType); // 型消去後のList<? extends Number>の具象化型 | |
// Java5の拡張APIを使いGenerics固有の情報を取得 | |
assertTrue(wildcardParameterizedField.getGenericType() instanceof ParameterizedType); | |
ParameterizedType parameterizedType = (ParameterizedType)wildcardParameterizedField.getGenericType(); | |
assertEquals(1, parameterizedType.getActualTypeArguments().length); | |
assertTrue(parameterizedType.getActualTypeArguments()[0] instanceof WildcardType); | |
assertEquals(List.class, parameterizedType.getRawType()); | |
WildcardType wildcardType = (WildcardType)parameterizedType.getActualTypeArguments()[0]; | |
assertArrayEquals(new Type[] {Number.class}, wildcardType.getUpperBounds()); | |
assertArrayEquals(new Type[0], wildcardType.getLowerBounds()); | |
} | |
/** | |
* 総称型配列T[]に対するリフレクション情報の取得 | |
*/ | |
@Test | |
public void typeVariableArrayField() throws Exception { | |
// JDK1.4までに存在していたAPIは型消去後の情報のみを返す。 | |
Field typeVariableArrayField = TypePatterns.class.getField("typeVariableArrayField"); | |
Class<?> typeVariableArrayFieldType = typeVariableArrayField.getType(); | |
assertEquals(Object[].class, typeVariableArrayFieldType); // 型消去後のT[]の具象化型 | |
assertTrue(typeVariableArrayFieldType.isArray()); | |
assertEquals(Object.class, typeVariableArrayFieldType.getComponentType()); | |
// Java5の拡張APIを使いGenerics固有の情報を取得 | |
assertTrue(typeVariableArrayField.getGenericType() instanceof GenericArrayType); | |
GenericArrayType genericArrayType = (GenericArrayType)typeVariableArrayField.getGenericType(); | |
assertTrue(genericArrayType.getGenericComponentType() instanceof TypeVariable); | |
TypeVariable<?> typeVariable = (TypeVariable<?>)genericArrayType.getGenericComponentType(); | |
assertEquals("T", typeVariable.getName()); // 型変数名「T」 | |
assertArrayEquals(new Type[]{Object.class}, typeVariable.getBounds()); // Tの上限(指定されていないためObject) | |
assertEquals(TypePatterns.class, typeVariable.getGenericDeclaration()); // Tの宣言はTypePatternsクラス | |
} | |
/** | |
* 総称型配列List<String>[]に対するリフレクション情報の取得 | |
*/ | |
@Test | |
public void parameterizedComponentArrayField() throws Exception { | |
// JDK1.4までに存在していたAPIは型消去後の情報のみを返す。 | |
Field parameterizedComponentArrayField = TypePatterns.class.getField("parameterizedComponentArrayField"); | |
Class<?> parameterizedComponentArrayFieldType = parameterizedComponentArrayField.getType(); | |
assertEquals(List[].class, parameterizedComponentArrayFieldType); // 型消去後のList<String>の具象化型 | |
assertTrue(parameterizedComponentArrayFieldType.isArray()); | |
assertEquals(List.class, parameterizedComponentArrayFieldType.getComponentType()); | |
// Java5の拡張APIを使いGenerics固有の情報を取得 | |
assertTrue(parameterizedComponentArrayField.getGenericType() instanceof GenericArrayType); | |
GenericArrayType genericArrayType = (GenericArrayType)parameterizedComponentArrayField.getGenericType(); | |
assertTrue(genericArrayType.getGenericComponentType() instanceof ParameterizedType); | |
ParameterizedType parameterizedType = (ParameterizedType)genericArrayType.getGenericComponentType(); | |
assertArrayEquals(new Type[]{String.class}, parameterizedType.getActualTypeArguments()); // 型変数に対するパラメーター値「String」 | |
assertEquals(List.class, parameterizedType.getRawType()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment