【问题标题】:Generics Vs. Arraylist?泛型与。数组列表?
【发布时间】:2016-06-28 19:50:20
【问题描述】:

我对 ArrayLists 和泛型有点困惑,例如,在下面的程序中,当我声明 Gen<Integer>iOb=new Gen<Integer>(88); 它声明了 Integer 的泛型类型是否正确?但是,如果我以同样的方式声明一个数组列表?在数组列表的情况下,它是尖括号中的类型,但是,研究泛型,它说尖括号中的类型是泛型类型?我如何知道它是类类型的数组列表还是泛型?

//A simple generic class 
//Here, T is a type parameter that
///will be replaced by a real type
//when an object of type gen is created
class Gen<T> {
    T ob;//declare an object of type T

    //Pass the constructor a refernce to
    //an object of type T 
    Gen(T o) {
        ob = o;
    }

    //return ob
    T getob() {
        return ob;
    }

    //show type of t
    void showType() {
        System.out.println("Type of T is " + ob.getClass().getName());
    }
}

class GenDemo {
    public static void main(String[] args) {
        //create a gen reference for integers
        Gen<Integer> iOb;
        //Create a Gen<Integer>Object and assign its 
        //reference to iob, notice the use  of autoboxing
        //to encapsulate the value 88 within an integer object 
        iOb = new Gen<Integer>(88);

        //show the type off data used by iob 
        iOb.showType();
        //get the value in Iob notice that no cast is needed
        int v = iOb.getob();
        System.out.println("Value: " + v);
        System.out.println();
        //create a gen object for strings
        Gen<String> strOb = new Gen<String>("Generic Test");
        //show the type of data 
        strOb.showType();
        //get the value of strOb, again notice that no cast is needed 
        String str = strOb.getob();
        System.out.println("Value  :" + str);
    }
}

【问题讨论】:

  • 这段代码中没有ArrayList。 ArrayList 是一个类。一个通用类。就像Gen。究竟是什么让您感到困扰?
  • 我知道这段代码中没有arraylist,但是arraylist和generic的声明方式完全相同,我怎么知道它是generic还是Gen类型的ArrayList?跨度>
  • 什么是“通用”?你读过docs.oracle.com/javase/tutorial/java/generics吗?
  • The tutorial 调用 Gen&lt;T&gt; 泛型类型,T 类型参数和 Gen&lt;Integer&gt; 参数化类型。
  • @jozencl,听起来,当您说“通用类型”时,您是在谈论其他人所说的 raw 类型。 ArrayList&lt;T&gt; 是泛型类型,ArrayList 是原始类型。您可以在代码中声明原始类型(例如,您可以声明一个引用 ArrayList 的变量,而无需说明 ArrayList 是什么,但如果这样做,您将不得不处理大量编译器警告。

标签: java generics arraylist


【解决方案1】:

您似乎混淆了泛型类型类型参数的概念。

鉴于你的班级:

class Gen<T> {
    // ...
}

Gen 是一个泛型类(一种特定的泛型类型),因为它被声明为具有至少一个类型参数,在本例中为T。当您实例化Gen 时,有时在其他情况下,您提供绑定到T 的类型表达式:

Gen<?> gen = new Gen<String>();

给定的类型表达式(?String)通常也称为“类型参数”,就像类Gen 中的T 定义一样。 特定类型参数可以由泛型类构成(例如:Gen&lt;List&lt;String&gt;&gt; 中的List&lt;String&gt;),但“泛型类”不是“类型参数”的同义词。

ArrayList 是一样的。它是具有一个类型参数的泛型类。特定的声明提供类型表达式作为这些类型参数的值:

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

List&lt;E&gt;ArrayList&lt;E&gt; 是泛型类型;后者具体是一个泛型类。两边的Integer是应用于list的声明和ArrayList的实例化的类型参数;在此上下文或任何其他上下文中,它不被称为“泛型类”。

【讨论】:

    【解决方案2】:

    当我声明时,Gen&lt;Integer&gt; iOb = new Gen(88); 它声明了一个 Integer 的泛型类型正确吗?

    这是不正确的。您正在声明/创建一个 Gen 对象,该对象包含一个 T extends Object。在Gen 代码中,您只能使用允许在Object 上使用的函数,例如getClass()

    Java 编译器记住iOb 将引用一个Gen 对象,必须拥有一个Integer 对象,并将根据getob() 的返回值生成自动类型转换。 .

    int v=iOb.getob();
    

    被编译器解释为如下内容:

    int v = (Integer) iObj.getob();
    

    getob() 被认为只返回一个Object。请注意,这是为了方便程序员而进行的编译时转换。

    但是,如果我以同样的方式声明一个数组列表呢?在数组列表的情况下,它是尖括号中的类型,但是,研究泛型,它说尖括号中的类型是泛型类型?我怎么知道它是一个类类型的数组列表还是泛型???

    class SomeClass&lt;T&gt; { ... } 声明一个泛型类型。尖括号之间的部分是泛型类的“类型参数”。

    当泛型类用作变量的类型时,它被认为是泛型类的特化,类型参数可以是具体类、接口或另一个泛型类。

    【讨论】:

      【解决方案3】:

      你的问题措辞有点奇怪,但我会试一试。泛型用于类型安全,特别是用于集合。如果你要像这样声明一个 ArrayList:

      ArrayList a= new ArrayList(); 
      

      然后您可以将任何类型的对象放入 ArrayList 中。这是非常危险的,因为当您从列表中检索对象时,您需要知道您将从列表中检索的对象类型。您不会想将 cat 对象拉入 person 引用中!猫不是人!这就是泛型的用武之地。像这样声明你的 ArrayList:

      ArrayList<People> p= new ArrayList<People>(); 
      

      允许您具有类型安全性。那些讨厌的 Cat 对象进入您的人员阵列不再有问题!

      至于这个:

      //get the value in Iob notice that no cast is needed
      
      int v = iOb.getob();
      

      您似乎对拆箱感到困惑。它与泛型无关。我建议您查看自动装箱和拆箱。

      终于:

        //get the value of strOb, again notice that no cast is needed
      
          String str = strOb.getob();
      

      我看不出你在这里不明白什么。字符串是对象。你把一个 String 对象放进去,然后你拉出一个 String 对象。

      我还建议创建一个简单的 java 对象,比如一个人,这样你就可以用你的 Gen 类创建一个泛型,比如 String,然后尝试将一个 Person 对象放入其中。看看它会出现什么错误。

      【讨论】:

        【解决方案4】:

        首先,我们应该澄清一些术语。来自https://docs.oracle.com/javase/tutorial/java/generics/why.html

        简而言之,泛型使类型(类和接口)在定义类、接口和方法时成为参数。就像在方法声明中使用的更熟悉的形式参数一样,类型参数为您提供了一种通过不同输入重用相同代码的方法。区别在于形式参数的输入是值,而类型参数的输入是类型。

        因此,当您执行 Gen&lt;Integer&gt;iOb=new Gen&lt;Integer&gt;(88); 时,Gen 类由 Gen 类型组成,但具有泛型类型参数 IntegerGen 是一个泛型类,因为类头包含一个泛型类型参数&lt;T&gt;。但是,Arraylist 也是泛型类,因为它们不限于一种类型,正如您从声明中可以看出的那样。声明 Arraylist 时,您可以按照与 Gen 类相同的方式进行类型声明。例如:Arraylist&lt;String&gt; list = new ArrayList&lt;String&gt;();

        Arraylists 确实有一个原始类型实现,它在声明中不需要类型参数。例如:Arraylist list = new Arraylist(); 但不建议这样做,如果您以这种方式声明数组列表,Java 实际上会给您一个警告,建议您对数组列表进行参数化。

        总之,泛型类型是在类型上参数化的泛型类或接口 (https://docs.oracle.com/javase/tutorial/java/generics/types.html)。所以你的Gen 类和Java 内置的Arraylist 类都是泛型类型。

        【讨论】:

          猜你喜欢
          • 2010-09-10
          • 1970-01-01
          • 1970-01-01
          • 2023-03-06
          • 1970-01-01
          • 1970-01-01
          • 2017-08-21
          • 2013-06-27
          • 1970-01-01
          相关资源
          最近更新 更多