Java泛型:从泛型对象中检索类型

huangapple go评论74阅读模式
英文:

Java Generics : Retrieving the type from a generic object

问题

我有一个通用类 Class1<K, V>,它接受两种类型。现在我想要维护一个将 String 映射到 Class1 对象的映射,即 Map<String, Class1>。当我遍历 Map 时,我能够获取每个 Class1 对象的类型 (K, V) 吗?

也就是说,让我们将代码想象成如下:

    Map<String, Class1> map;
    map.put("1", Class1<String, Integer> obj1);
    map.put("2", Class1<String, Double> obj2);
    map.put("3", Class1<Integer, Double> obj3);

现在,当我遍历该映射时,我能否以某种方式获取每个 Class1 对象的类型 (K, V)?
英文:

I have a generic class Class1<K, V> which takes two types. Now I want to maintain a map which maps String to Class1 objects i.e Map<String, Class1> . Can I retrieve the types (K,V) of each Class1 Object while I iterate through Map?

i.e lets think of code as below

Map&lt;String, Class1&gt; map;
map.put(&quot;1&quot;, Class1&lt;String, Integer&gt; obj1);
map.put(&quot;2&quot;, Class1&lt;String, Double&gt; obj2);
map.put(&quot;3&quot;, Class1&lt;Integer, Double&gt; obj3);

Now when I iterate over the map ... Can I somehow get the types(K, V) of each Class1 object??

答案1

得分: 1

根据JVM规范,这是不可能的。

泛型类型仅在编译时可用。在运行时,它们只是Object类型。

你只有两个选项:

  1. 为你的对象添加类定义变量,并在需要这些信息时使用它。
  2. 例如,对于List<Object>以及其他集合,如果不为空,你可以从中获取一个项目并调用item.getClass()

附注: 顺便说一下,你的方法不正确,不能解决这个问题。你可以实现一个接口,类似于:

interface TypeConverter {
    boolean isValid(String str);   // 在转换之前调用它,检查当前转换器是否适用于所需的转换

    Class1 converts(String str);  // 调用它进行转换 
}

对于每种所需的类型,你都需要创建单独的转换器(这是策略模式)。你的最终代码可能如下所示:

final List<TypeConverter> converters = new ArrayList<>();
converters.add(new OneTypeConverter());
converters.add(new TwoTypeConverter());

public static Class1 convert(String str) {
    for (TypeConverter converter : converters) {
        if (converter.isValid(str)) {
            return converter.convert(str);
        }
    }
  
    throw new RuntimeException("找不到合适的转换器");
}
英文:

It's not possible according to JVM specification.

Generic types are available only at compile time. At runtime ther're only Object.

All you have is 2 options:

  1. Add class definition variable to your objects and us it when you need this info.
  2. E.g. for List&lt;Object&gt; as well as for other collections if it's not empty, you can get an item from it and get item.getClass().

P.S. Buy the way, your approach is not correct to solve this issue. You could implement an interface like:

interface TypeConverter {
    boolean isValid(String str);   // call it before to check if current converter valid for required transform or not

    Class1 converts(String str);  // call it to convert 
}

And for each required types you have to create separate converter (this is Strategy Pattern). And your final code could look like this:

final TypeConverter converters = new ArrayList&lt;&gt;();
converters.add(new OneTypeConverter());
converters.add(new TwoTypeConverter());

public static Class1 convert(String str) {
    for(TypeConverter convereter : converters)
        if(converter.isValid(str))
            return converter.convert(str);
  
    throw new RuntimeException(&quot;No suitable converter found&quot;);
}

huangapple
  • 本文由 发表于 2020年8月31日 20:02:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/63670455.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定