【问题标题】:Can an object of a generic class be created with any type, T?可以用任何类型 T 创建泛型类的对象吗?
【发布时间】:2018-05-03 23:41:57
【问题描述】:

我学到了关于泛型类的基本概念是可以用另一个类参数化的类 (或类型)。我给出的例子是ArrayList<E>。

泛型类是专门引用ArrayList 还是任何类型?

【问题讨论】:

标签: java generics data-structures types


【解决方案1】:

所有用< .. >声明的类都是泛型类。

某个给定类型 T 的 ArrayList 声明为:

ArrayList<T> list = new ArrayList<T>()

ArrayList 持有整数(当打算持有int)应该是

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

您也可以创建自己的泛型类(这里是一个包含某些未指定类型的单链表的节点E)

class Node<E> {
    private E element;
    private Node<E> next;

    public Node(E element) {
        this.element = element;
        this.next = null;
    }

    public E getElement() {
        return this.element;
    }

    public Node<E> getNext() {
        return this.next;
    }
}

注意:T 不能是基本类型,例如 char、int、boolean、double。您必须使用包装器,例如 Character、Integer、Boolean 或 Double。

【讨论】:

  • T是指任何类型,包括原始类型和引用类型吗?
  • T 不能是原始类型。相反,使用包装器类型。
  • 那么 E 是比 T 更小的类型吗?
  • E 不是比 T 更小的类型。和 T 一样,E 不能是原始类型。符号T 和E 只是约定,表示未指定的类。 T 代表“类型”,E 代表“该类型的元素(T)`
  • T 代表任何非原始类型。请记住,您的 ArrayList&lt;E&gt; 属于 未指定类型 E。 T、E,用于创建自己的泛型类型。
【解决方案2】:

Java 中的泛型类似于 C++ 中的模板。这个想法是允许类型(整数、字符串等和用户定义的类型)作为方法、类和接口的参数。例如,HashSet、ArrayList、HashMap 等类都很好地使用了泛型。我们可以将它们用于任何类型。

通用类:

要创建泛型类的对象,我们使用以下语法。

// 创建泛型类的实例 BaseType obj = new BaseType ()

注意:在参数类型中我们不能使用像 'int'、'char' 或 'double'。

// A Simple Java program to show working of user defined
// Generic classes

// We use < > to specify Parameter type
class Test<T>
{
    // An object of type T is declared
    T obj;
    Test(T obj) {  this.obj = obj;  }  // constructor
    public T getObject()  { return this.obj; }
}

// Driver class to test above
class Main
{
    public static void main (String[] args)
    {
        // instance of Integer type
        Test <Integer> iObj = new Test<Integer>(15);
        System.out.println(iObj.getObject());

        // instance of String type
        Test <String> sObj =
                          new Test<String>("GeeksForGeeks");
        System.out.println(sObj.getObject());
    }
}

我们还可以在 Generic 类中传递多个 Type 参数。

// A Simple Java program to show multiple
// type parameters in Java Generics

// We use < > to specify Parameter type
class Test<T, U>
{
    T obj1;  // An object of type T
    U obj2;  // An object of type U

    // constructor
    Test(T obj1, U obj2)
    {
        this.obj1 = obj1;
        this.obj2 = obj2;
    }

    // To print objects of T and U
    public void print()
    {
        System.out.println(obj1);
        System.out.println(obj2);
    }
}

// Driver class to test above
class Main
{
    public static void main (String[] args)
    {
        Test <String, Integer> obj =
            new Test<String, Integer>("GfG", 15);

        obj.print();
    }
}

通用函数:

我们还可以编写泛型函数,根据传递给泛型方法的参数类型,使用不同类型的参数调用,编译器处理每个方法。

// A Simple Java program to show working of user defined
// Generic functions

class Test
{
    // A Generic method example
    static <T> void genericDisplay (T element)
    {
        System.out.println(element.getClass().getName() +
                           " = " + element);
    }

    // Driver method
    public static void main(String[] args)
    {
         // Calling generic method with Integer argument
        genericDisplay(11);

        // Calling generic method with String argument
        genericDisplay("GeeksForGeeks");

        // Calling generic method with double argument
        genericDisplay(1.0);
    }
}

泛型的优点:

使用泛型的程序比非泛型代码有很多好处。

Code Reuse: We can write a method/class/interface once and use for any type we want.

.
Type Safety : Generics make errors to appear compile time than at run time (It’s always better to know problems in your code at compile time rather than making your code fail at run time). Suppose you want to create an ArrayList that store name of students and if by mistake programmer adds an integer object instead of string, compiler allows it. But, when we retrieve this data from ArrayList, it causes problems at runtime.


     // A Simple Java program to demonstrate that NOT using
        // generics can cause run time exceptions
        import java.util.*;

        class Test
        {
            public static void main(String[] args)
            {
                // Creatinga an ArrayList without any type specified
                ArrayList al = new ArrayList();

                al.add("Sachin");
                al.add("Rahul");
                al.add(10); // Compiler allows this

                String s1 = (String)al.get(0);
                String s2 = (String)al.get(1);

                // Causes Runtime Exception
                String s3 = (String)al.get(2);
            }
        }

Output :

Exception in thread "main" java.lang.ClassCastException: 
   java.lang.Integer cannot be cast to java.lang.String
    at Test.main(Test.java:19)

泛型如何解决这个问题? 在定义 ArrayList 的时候,我们可以指定这个列表只能取 String 对象。 // 使用泛型将运行时异常转换为 // 编译时异常。 导入 java.util.*;

class Test
{
    public static void main(String[] args)
    {
        // Creating a an ArrayList with String specified
        ArrayList <String> al = new ArrayList<String> ();

        al.add("Sachin");
        al.add("Rahul");

        // Now Compiler doesn't allow this
        al.add(10); 

        String s1 = (String)al.get(0);
        String s2 = (String)al.get(1);
        String s3 = (String)al.get(2);
    }
}

Output:

15: error: no suitable method found for add(int)
        al.add(10); 
          ^

。 不需要单独的类型转换:如果我们不使用泛型,那么在上面的示例中,每次我们从 ArrayList 检索数据时,我们都必须对其进行类型转换。每次检索操作的类型转换都是一件令人头疼的事情。如果我们已经知道我们的列表只包含字符串数据,那么我们不需要每次都对其进行类型转换。

// We don't need to typecast individual members of ArrayList
import java.util.*;

class Test
{
    public static void main(String[] args)
    {
        // Creating a an ArrayList with String specified
        ArrayList <String> al = new ArrayList<String> ();

        al.add("Sachin");
        al.add("Rahul");

        // Typecasting is not needed 
        String s1 = al.get(0);
        String s2 = al.get(1);
    }
}

。 实现泛型算法:通过使用泛型,我们可以实现适用于不同类型对象的算法,同时它们也是类型安全的。

【讨论】:

    猜你喜欢
    • 2011-08-13
    • 2013-08-29
    • 2014-04-04
    • 2010-10-13
    • 1970-01-01
    • 2017-12-14
    • 1970-01-01
    相关资源
    最近更新 更多