Skip to content

Instantly share code, notes, and snippets.

@ryoasai
Created March 26, 2011 12:45
Show Gist options
  • Save ryoasai/888253 to your computer and use it in GitHub Desktop.
Save ryoasai/888253 to your computer and use it in GitHub Desktop.
Various Java5 type patterns to demonstrate generics reflection API.
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