- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
给出下面的代码片段,对于 POJO 类的每个字段,有没有办法检查类型是否是整数列表?这里真正的问题是类型参数,因为通过 instanceof
或 isAssignableFrom
很容易检查它是否是一个列表。
main
中的行是我目前所发现的,但它不适用于那些具有更复杂类层次结构的类型。
public class Test {
public static void main(String[] args) throws NoSuchFieldException {
// to check if field f1 is an integer list
Field field = Pojo.class.getField("f1");
if (List.class.isAssignableFrom(field.getType())) {
Type type = field.getGenericType();
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
if (pt.getActualTypeArguments()[0].equals(Integer.class)) {
System.out.println("Yes, it's an integer list");
}
}
}
}
public static class Pojo {
public List<Integer> f1;
public ArrayList<Integer> f2;
public C1 f3;
public C2<Integer> f4;
public C3<Integer> f5; // notice, this is not an integer list, it's a string list
public C4<Integer> f6;
public C5<String, Integer> f7;
}
public static class C1 implements List<Integer> {...}
public static class C2<T> implements List<T> {...}
public static class C3<T> implements List<String> {...}
public static class C4<T> implements List<Integer> {...}
public static class C5<T1, T2> implements List<T2> {...}
}
最佳答案
你是对的,因为删除,这不是一个容易的问题。但是,我认为这并非无法解决。
基本原则应该是一直到List<E>
都遵循并用实际参数类型替换类型变量。 .
考虑这两个类:
class B<T> extends AbstractList<T>{}
class A<E> extends B<E>{}
B
声明中使用的类型变量名是T
,而当它从 A
中扩展时, E
用来。因此,我们不能依赖声明的名称。
Field
开始直到我们点击 List<E>
. (我不确定当 List 通过不止一条路径进入层次结构时会发生什么。因此,下面没有处理这种情况。)E
时在 List
最后,我们可以得出结论,如果它是 List<Integer>
还是不是。这是执行此操作的代码。这是相当多的行,但适用于您添加的案例(以及我这边的更多案例)。实现过程中可能存在一些缺陷,但这种方法应该有效。
public class ParameterizedTypeHierarchy{
/* When a conclusion is reached - negative or positive - about a field, one of these exceptions is thrown to
* quickly return to the main(). */
private static class NotListOfIntegerException extends RuntimeException{
private Type elementType;
public NotListOfIntegerException( Type elementType ){
this.elementType = elementType;
}
}
private static class IsAListOfIntegerException extends RuntimeException{}
public static void main( String[] args ) throws NoSuchFieldException{
List<String> fields = Arrays.asList( "f0", "f1", "f2", "c1", "c2", "c3", "c4",
"c5", "c5Neg1", "c6", "c6Neg1", "c7", "c7Neg1", "c7Neg2" );
for( String f : fields ){
// to check if field f1 is an integer list
Field field = Pojo.class.getField( f );
try{
check( field );
}
catch( IsAListOfIntegerException e ){
System.out.println( f + " (" + field.getType().getSimpleName() + ") is a List<Integer>" );
}
catch( NotListOfIntegerException e ){
if( e.elementType == null ) System.out.println( f + " (" + field.getType().getSimpleName() + ") is NOT a List." );
else System.out.println( f + " (" + field.getType().getSimpleName() + ") is NOT a List<Integer>. It is List<" + e.elementType.getTypeName() + ">." );
}
catch( Exception e ){
e.printStackTrace();
}
}
}
private static boolean check( Field f ){
Type type = f.getGenericType();
if( type instanceof ParameterizedType ){
/* Parameterized type field. */
if( isList( (ParameterizedType) type, null, null ) ) return true;
}
else if( type instanceof Class ){
/* Field's type takes no parameters. */
return fromClass( (Class<?>) type );
}
return false;
}
private static boolean fromClass( Class<?> type ){
/* For class there are ways in which a List could be one of its parents: interface implementations
* or the super class indirectly being a child of List. */
Type[] intfs = type.getGenericInterfaces();
if( intfs != null && intfs.length > 0 ){
for( Type intf : intfs ){
if( intf instanceof ParameterizedType && isList( (ParameterizedType) intf, type, null ) ) return true;
}
}
Type st = type.getGenericSuperclass();
/* If there is no super class or the super is Object, we can conclude in the negative. */
if( st == null || Object.class == st ) throw new NotListOfIntegerException( null );
if( st instanceof ParameterizedType ){
if( isList( (ParameterizedType) st, type, null ) ) return true;
}
return false;
}
private static boolean isList( ParameterizedType pt, Class<?> extendingEntity, Type[] types ){
/* This parameterized type needs to be a list. Else return. */
Type raw = pt.getRawType();
if( raw instanceof Class && !List.class.isAssignableFrom( (Class<?>) raw ) ) return false;
Type[] listParamTypes = pt.getActualTypeArguments();
/* If this is directly List.class, then we can decide here itself. */
if( raw == List.class ) return listParamTypes[ 0 ] == Integer.class;
/* This is a parameterized class that implements List. However, the extending class's parameter(s) need not be for
* List. Hence, we have get the RIGHT parameters for the parameterized type and check against them. */
Type[] replaced = replaceTypeVars( pt, extendingEntity, types );
Class<?> c = (Class<?>) raw;
return classExtList( c, replaced );
}
private static Type[] replaceTypeVars( ParameterizedType pt, Class<?> impl, Type[] types ){
Map<String, Type> repl = replacements( impl, types );
Type raw = pt.getRawType();
Type[] rawTypeParams = null;
if( raw instanceof Class<?> ){
Class<?> c = (Class<?>) raw;
Type[] actual = pt.getActualTypeArguments();
if( actual == null || actual.length == 0 ) return null;
rawTypeParams = new Type[ actual.length ];
for( int i = 0; i < actual.length; i++ ){
Type tv = actual[ i ];
Type val = null;
if( !( tv instanceof TypeVariable ) ){
rawTypeParams[ i ] = actual[ i ];
}
else{
if( ( val = repl.get( ( (TypeVariable<?>) tv ).getName() ) ) == null )
rawTypeParams[ i ] = tv;
else
rawTypeParams[ i ] = val;
}
}
}
return rawTypeParams;
}
/* Replaces the type variables declared on a class with the actual parameters passed. */
private static Map<String, Type> replacements( Class<?> c, Type[] types ){
if( c == null ) return Collections.emptyMap();
TypeVariable<?>[] tps = c.getTypeParameters();
if( tps == null || tps.length == 0 ) return Collections.emptyMap();
Map<String, Type> map = new HashMap<>();
for( int i = 0; i < tps.length; i++ ){
/* Skip TypeVariable instances. We want only replaced ones. */
if( types[ i ] instanceof TypeVariable ) continue;
TypeVariable<?> tv = tps[ i ];
map.put( tv.getName(), types[ i ] );
}
return map;
}
private static boolean classExtList( Class<?> c, Type[] types ){
TypeVariable<?>[] params = c.getTypeParameters();
Type[] intfs = c.getGenericInterfaces();
for( Type intf : intfs ){
/* If this interface is List and is taking Integer as param, great. */
if( intf instanceof ParameterizedType ){
ParameterizedType pt = (ParameterizedType) intf;
if( pt.getRawType() == List.class ){
/* If the type argument is Integer.class, we are done. */
if( pt.getActualTypeArguments()[ 0 ] == Integer.class ) throw new IsAListOfIntegerException();
/* Type argument is the type variable itself. We have to check which type variable
* was passed to List. */
for( int i = 0; i < params.length; i++ ){
if( params[ i ].getName().equals( pt.getActualTypeArguments()[ 0 ].getTypeName() ) ){
if( types[ i ] == Integer.class ) throw new IsAListOfIntegerException();
throw new NotListOfIntegerException( types[ i ] );
}
}
}
}
}
Type st = c.getGenericSuperclass();
if( st instanceof ParameterizedType ) return isList( (ParameterizedType) st, c, types );
return false;
}
public static class Pojo {
public Object f0;
public List<Integer> f1;
public ArrayList<Integer> f2;
public C1 c1;
public C2<Integer> c2;
public C3<Integer> c3; // notice, this is not an integer list, it's a string list
public C4<Integer> c4;
public C5<String, Integer> c5;
public C5<String, String> c5Neg1;
public C6<String, Integer> c6;
public C6<String, String> c6Neg1;
public C7<String, Integer> c7;
public C7<String, String> c7Neg1;
public C7<String, ?> c7Neg2;
}
private static interface A<E>{}
private static class B<T> extends AbstractList<T> {
@Override
public T get( int index ){ return null; }
@Override
public int size(){ return 0; }
}
public static class C1 extends B<Integer> {}
public static class C2<T> extends B<T> {}
public static class C3<T> extends B<String> {}
public static class C4<T> extends B<Integer> {}
public static class C5<T1, T2> extends B<T2> {}
public static class C6<T1, T2> implements List<T2> {...}
public static class C7<T1, T2> implements List<T2>, A<T1>{...}
}
关于java - 如何检查一个 ParameterizedType 是否代表另一个 ParameterizedType 的子类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70105878/
我有这个 html 代码: HELLO WORLD! X V HELLO WORLD! X V 我想按 X(类关闭)将父 div 的高度更改为 20px 并显示 V(类打开),但在每个 d
在会计应用程序的许多不同实现中,有两种主要的数据库设计方法来保存日志和分类帐数据。 只保留 Journal 信息,然后 Ledger 只是 Journal 的一个 View (因为 journal 总
我想在另一个子里面有一个子, sub a { sub b { } } 我想为每次调用 sub b 创建一个新的 sub a 实例。有没有办法在 Perl 中做到这一点? 当我运行上面的
我有一些代码正在查找重复项并突出显示单元格: Private Sub cmdDups_Click() Dim Rng As Range Dim cel As Range Set Rng = ThisW
可能有一个简单的解决方案,但我很难过。 我有一个包含一个 ID 字段的主表。在两个可能的字段中有一个具有该 ID 的子表。想象一个由选手 A 和选手 B 组成的 double 队。Master 表将有
假设我有一个包含对象的数组: [ { "id": "5a97e047f826a0111b754beb", "name": "Hogwarts", "parentId": "
我正在尝试对 MySQL 数据库表执行一对父/子模型的批量插入,但似乎无法使用标准的 ActiveRecord 功能来完成。所以,我尝试了 activerecord-import gem,但它也不支持
我有一个带有多个子类的父抽象类。最终,我希望通过 GUI 中的进度条显示子类中完成的进度。 我目前所做的,我意识到这是行不通的,是在父类中声明为每个子类将覆盖的虚拟方法的事件方法定义。所以像: pub
是否可以通过键数组在对象中设置变量?例如我有这个对象: var obj = {'outer': {'inner': 'value'} }; 并希望设置由键数组选择的值: var keys = ['ou
我有一个名为 companies 的 MySQL 表,如下所示: +---------+-----------+-----------+ | id_comp | comp_name | id_pare
我正在尝试使用 sublime text 在 sublime text 上的 ionic 上打开我的第一个应用程序。它给了我一个“找不到命令”的错误。如何修复? 我试过这些命令: sudo rm -r
不好意思问,但我正在使用 webapp2,我正在设计一个解决方案,以便更容易定义路由 based on this google webapp2 route function .但这完全取决于能够在子级
我有代表树的数字字符串(我不知道是否有官方名称): 012323301212 上面的例子代表了 2 棵树。根用 0 表示。根的直接子代为“1”,“1”的直接子代为“2”,依此类推。我需要将它们分组到由
是否可以在当前 Activity 之上添加 Activity 。例如,假设我单击一个按钮,然后它将第二个 Activity 添加到当前 Activity 。而第二个 Activity 只覆盖了我当前
我很难思考如何为子资源建模。 以作者的书籍为例。你可以有 N 本书,每本书只有一位作者。 /books GET /books POST /books/id PUT /books/id DELETE 到
有人可以向我解释以下内容(python 2.7) 来自已解析文件的两个字符串数字: '410.9''410.9 '(注意尾随空格) A_LIST = ['410.9 '] '410.9' in '41
背景 在 PowerShell 中构建 hash table 是很常见的通过特定属性快速访问对象,例如以 LastName 为基础建立索引: $List = ConvertFrom-Csv @' I
我真的很难弄清楚如何调用嵌套 Polymer Web 组件的函数。 这是标记: rise-distribution组件有 canPlay我想从 rise-playlist
我写了一个小工具转储(以 dot 格式)一个项目的依赖关系图,其中所有位于同一目录中的文件都聚集在一个集群中。当我尝试生成包含相应图形的 pdf 时,dot开始哭: 命令 dot -Tpdf trim
给定一个 CODE ref,是否可以: 访问该 CODE ref 的解析树 通过指定 CODE ref 的解析树来创建一个新的 CODE ref,该解析树可以包含在 1 中返回的解析树的元素 通常我们
我是一名优秀的程序员,十分优秀!