В моем редакторе POJO мне нужно проверить, можно ли создать экземпляр класса, предоставленный пользователем, и назначить его универсальному свойству. Отражение гуавы обеспечивает почти все, что мне нужно: я разрешаю типы и затем вызываю proptype.isSupertypeOf(implClazz)
, но это не работает, как ожидалось.
Например, у меня есть токен типа: java.util.Collection<java.sql.Timestamp>
, и я хочу, чтобы моя проверка принимала ArrayList
, а классы, которые расширяют raw ArrayList
или ArrayList<Timestamp>
, либо сами параметризованы, но не принимают класс, который расширяет ArrayList<Integer>
.
Однако isSupertypeOf()
хорошо работает только с полностью разрешенными типами, тогда как неполные и необработанные классы не рассматриваются как подтипы.
package com.common.jsp.beans;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import com.google.common.reflect.TypeToken;
public class TestTypeInf
{
public static class MyCollection1 extends ArrayList<Integer> {
}
public static class MyCollection2 extends ArrayList<Timestamp> {
}
public static class MyCollection3<T> extends ArrayList<T> {
}
public static class MyCollection4 extends ArrayList {
}
public static Collection<Timestamp> fld;
public static void main( String[] args )
throws Exception
{
// bad: fld = new MyCollection1();
fld = new MyCollection2();
fld = new MyCollection3(); // just a warning
fld = new MyCollection4(); // just a warning
Field getter = TestTypeInf.class.getField( "fld" );
Type memberType = getter.getGenericType();
TypeToken<?> resolved = TypeToken.of( TestTypeInf.class ).resolveType( memberType );
System.out.println( "type of fld: " + resolved );
checkAssignable(resolved, MyCollection1.class);
checkAssignable(resolved, MyCollection2.class);
checkAssignable(resolved, MyCollection3.class); // This should be totally valid
checkAssignable(resolved, MyCollection4.class); // why no?
}
private static void checkAssignable(TypeToken<?> resolved, Class<?> implClass) {
System.out.println( "fld = new " + implClass.getSimpleName() + "()" );
System.out.println( resolved.isSupertypeOf( implClass ) ? "yes" : "no" );
}
}
_
type of fld: java.util.Collection<java.sql.Timestamp>
fld = new MyCollection1()
no
fld = new MyCollection2()
yes
fld = new MyCollection3()
no
fld = new MyCollection4()
no
fld = new ArrayList()
no