映射值的Java泛型

映射值的Java泛型,java,generics,Java,Generics,我想在下面的场景中直接转换为适当的列表类型。如果擦除杀死了类类型信息,那么在下面的场景中维护类类型的最佳方法是什么 class MyProperties { private final Map<String, List<?>> properties = new HashMap<>(); public void put(final String key, final List<?> value) { propert

我想在下面的场景中直接转换为适当的列表类型。如果擦除杀死了类类型信息,那么在下面的场景中维护类类型的最佳方法是什么

class MyProperties {

    private final Map<String, List<?>> properties = new HashMap<>();

    public void put(final String key, final List<?> value) {
        properties.put(key, value);
    }

    public <T> List<T> get(final String key, final Class<T> t) {
        final List<?> object = properties.get(key);
        // Here is where the issue lies because the class type is gone, so we
        // will always skip this block and return null
        if (object.getClass().isAssignableFrom(t)){
            return (List<T>)object;
        }
        return null;
    }

    public static void main(String[] args){
        List<String> myList = new ArrayList<>();
        myList.add("Bacon");
        myList.add("Eggs");

        List<Integer> myList2 = new ArrayList<>();
        myList2.add(1);
        myList2.add(2);

        MyProperties props = new MyProperties();
        props.put("myKey", myList);
        props.put("myKey2", myList2);

        // I'd like to directly cast to the appropriate list type if possible
        List<String> foo = props.get("myKey", String.class);
        List<Integer> foo2 = props.get("myKey2", Integer.class);
    }    
}
类属性{
私有最终映射对象=properties.get(key);
//这就是问题所在,因为类类型已经不存在了,所以我们
//将始终跳过此块并返回null
if(object.getClass().isAssignableFrom(t)){
返回(列表)对象;
}
返回null;
}
公共静态void main(字符串[]args){
List myList=new ArrayList();
myList.添加(“培根”);
myList.添加(“鸡蛋”);
List myList2=new ArrayList();
myList2.添加(1);
myList2.添加(2);
MyProperties props=新的MyProperties();
道具放置(“myKey”,myList);
道具放置(“myKey2”,myList2);
//如果可能的话,我想直接转换为适当的列表类型
List foo=props.get(“myKey”,String.class);
List foo2=props.get(“myKey2”,Integer.class);
}    
}

存储元素类型

public <T> List<T> get(final String key, final Class<T> t) {
  Class<?> propClass = propClasses.get( key );                  
  if( propClass == null || t == null || !t.equals( propClass )  ) {
    return null;
  }

  return (List<T>)properties.get(key);        
}
您可以做的是同时传递列表元素的类,并将其单独存储:

private final Map<String, List<?>> properties = new HashMap<>();
private final Map<String, Class<?>> propClasses= new HashMap<>();

public <T> void put(final String key, final List<T> value, final Class<T> elementClass) {
  properties.put(key, value);
  propClasses.put(key, elementClass);
}
检索具有确切元素类型的列表

public <T> List<T> get(final String key, final Class<T> t) {
  Class<?> propClass = propClasses.get( key );                  
  if( propClass == null || t == null || !t.equals( propClass )  ) {
    return null;
  }

  return (List<T>)properties.get(key);        
}
检索元素类型为下限的列表(只读)

如果要使用元素类的超类,可以更改
get()
方法或添加“只读”方法,如下所示:

public <T> List<? extends T> getReadOnly(final String key, final Class<T> t) {
  Class<?> propClass = propClasses.get( key );          
  if( propClass == null || t == null || !t.isAssignableFrom( propClass ) ) {
    return null;
  }

  return (List<? extends T>)properties.get(key);        
}

存储元素类型

public <T> List<T> get(final String key, final Class<T> t) {
  Class<?> propClass = propClasses.get( key );                  
  if( propClass == null || t == null || !t.equals( propClass )  ) {
    return null;
  }

  return (List<T>)properties.get(key);        
}
您可以做的是同时传递列表元素的类,并将其单独存储:

private final Map<String, List<?>> properties = new HashMap<>();
private final Map<String, Class<?>> propClasses= new HashMap<>();

public <T> void put(final String key, final List<T> value, final Class<T> elementClass) {
  properties.put(key, value);
  propClasses.put(key, elementClass);
}
检索具有确切元素类型的列表

public <T> List<T> get(final String key, final Class<T> t) {
  Class<?> propClass = propClasses.get( key );                  
  if( propClass == null || t == null || !t.equals( propClass )  ) {
    return null;
  }

  return (List<T>)properties.get(key);        
}
检索元素类型为下限的列表(只读)

如果要使用元素类的超类,可以更改
get()
方法或添加“只读”方法,如下所示:

public <T> List<? extends T> getReadOnly(final String key, final Class<T> t) {
  Class<?> propClass = propClasses.get( key );          
  if( propClass == null || t == null || !t.isAssignableFrom( propClass ) ) {
    return null;
  }

  return (List<? extends T>)properties.get(key);        
}

您正试图使用泛型方法签名强制执行类型完整性。但它显然会在编译后被擦除(类型擦除)

因此,您需要将类型实际存储为对象。这样,编译后类型信息不会丢失


因为每个键需要存储一个类型,所以数据结构的明显选择是额外的
Map您试图使用泛型方法签名来强制类型完整性。但它显然会在编译后被擦除(类型擦除)

因此,您需要将类型实际存储为对象。这样,编译后类型信息不会丢失


由于每个键需要存储一种类型,数据结构的明显选择将是额外的
映射。在许多其他问题中,
object.getClass()
将返回一个基于
列表的类,因为
object
是一个
列表
。。。它永远不会从
字符串
整数
中赋值,这与类型擦除无关。是的,没错。这是我一直坚持的部分,因为我认为一定有更好的方法来实现这一点。我不想将列表包装在一个跟踪列表及其类型的新类中。还要记住,
class
有一个方法。在许多其他问题中,
object.getClass()
将返回一个基于
List
的类,因为
object
是一个
List
。。。它永远不会从
字符串
整数
中赋值,这与类型擦除无关。是的,没错。这是我一直坚持的部分,因为我认为一定有更好的方法来实现这一点。我不想把列表包装成一个新的类来跟踪列表和它的类型还记得
class
有一个方法。谢谢你的建议。非常彻底!谢谢你的建议。非常彻底!