【问题标题】:Specifying a generic type in java from Class object从 Class 对象指定 java 中的泛型类型
【发布时间】:2013-03-07 19:49:39
【问题描述】:

为什么这是错误的:

    Class<? extends Number> type = Integer.class;
    ArrayList<type> = new ArrayList<>();

?

有没有办法在给定类对象的情况下实例化特定类型的类?


显然,我永远不会直接这样做,这只是展示所需内容的示例。在我需要的实际代码中,我不知道类型的名称。例如

    public void createAList(Class<? extends Number> type)  
{
    ArrayList<type> toReturn = new ArrayList<>();
    return toReturn;
}

【问题讨论】:

    标签: java generics reflection


    【解决方案1】:
    <T extends Number> ArrayList<T> createAList(Class<T> type)  
    {
        ArrayList<T> toReturn = new ArrayList<>();
        return toReturn;
    }
    
    
    ArrayList<Integer> intList = createAList(Integer.class);
    

    【讨论】:

    • 哇,成功了!我唯一不清楚的是它为什么起作用。您是否有任何链接可以非常详细地解释这一点?
    • @CarrKnight 这个答案巧妙地表明这种方法完全没有意义。请注意,type 甚至没有在其正文中使用。
    • 是的,但同样,这是堆栈溢出的简化示例。我使用类型参数来创建几个实例并在“列表”中返回它们。
    • @CarrKnight 那么这与您发布的问题大不相同。以当前形式查看问题的my answer
    【解决方案2】:

    这不是你使用泛型的方式。您不使用 Class 对象,而是直接在代码中使用类名。

    ArrayList<Integer> = new ArrayList<>();
    

    【讨论】:

    • 谢谢!但是我对不知道班级名称的情况感兴趣。但我确实在对象类中有这些信息
    • 您编辑的问题让您更清楚您想要什么。如果您有Class 对象,请使用@irreputable 的答案。
    【解决方案3】:

    感受一下 java Class(实际上也是通用的)对象和类名之间的区别。

    你应该使用类名来指定泛型。

    ArrayList<Number> = new ArrayList<>();
    // ArrayList<Number.class> = new ArrayList<>(); <- WRONG
    

    更新:

    如果您只在运行时知道类型,请使用此方法:

    public <T extends Number> void createAList(Class<T> type) {
        ArrayList<T> toReturn = new ArrayList<>();
        return toReturn;
    }
    

    【讨论】:

      【解决方案4】:

      ArrayList&lt;&gt; 必须具有它所拥有的特定类型。不过,您可以在其中放入该类型或任何子类型的对象。

      所以用

      List<Number> = new ArrayList<Number>();
      

      你可以把Integers放进去

      注意我是如何使用左边的接口和等号右边的类的。这是一种最佳实践。

      如果您想要一个仅包含Integer 的列表(根据您的示例),@irreputable 的答案是您最好的选择。这个答案将持有Integer,但不仅仅是Integer.

      【讨论】:

      • 谢谢!但是我对我不知道班级名称的情况感兴趣。但我确实在对象类中有这些信息。看看我的编辑是否让它更清晰
      【解决方案5】:

      从字面上看,其他答案关于如何实现createAList 的建议忽略了一些重要的事情:由于type erasure,这种方法毫无意义。

      如果你想要List&lt;? extends Number&gt;,你可以这样写:

      List<? extends Number> lst = new ArrayList<>();
      

      如果你只是想要List&lt;?&gt;,你可以写:

      List<?> lst = new ArrayList<>();
      

      如果您在类型参数T 的范围内并且想要List&lt;T&gt;,您可以这样写:

      List<T> lst = new ArrayList<>();
      

      请注意,Class 对象与这些构造函数调用无关,就像其他答案中的方法一样。这是因为在运行时,ArrayList 实例不知道也不关心其引用在运行时的泛型类型。

      【讨论】:

        【解决方案6】:

        你甚至不需要传入参数:

        public <T extends Number> ArrayList<T> createAList () {
            return new ArrayList<T>();
        }
        

        虽然你可能需要在调用时明确指定类型参数:

        ArrayList<Integer> intList = this.<Integer>createAList();
        

        【讨论】:

          【解决方案7】:
          ArrayList<type> = new ArrayList<>();
          

          这条线是错误的。首先,您在这里错过了标识符(变量名);其次,您混合了“类型”和“类”的概念。你可以不关心

          ArrayList<Integer> list = new ArrayList<>();
          

          但根据你的说法,type = Integer.class。显然,Integer 不等同于Integer.class。同样你不能有Integer.class i = 1; 前一个是“类型”,第二个是“类”对象。

          你可以创建一个泛型方法:

          public <T extends Number> List<T> createAList (Class<T> type) {
              return new ArrayList<T>();
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-08-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-05-26
            • 2018-08-24
            • 2010-11-07
            相关资源
            最近更新 更多