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);
}
}
。
实现泛型算法:通过使用泛型,我们可以实现适用于不同类型对象的算法,同时它们也是类型安全的。