仿制药 方法 参数类型 其思想是允许类型(整数、字符串等,以及用户定义的类型)成为方法、类和接口的参数。使用泛型,可以创建使用不同数据类型的类。在参数化类型上操作的类、接口或方法等实体是泛型实体。
为什么是仿制药?
这个 对象 是所有其他类的超类,对象引用可以引用任何对象。这些特性缺乏类型安全性。仿制药增加了这种类型的安全功能。我们将在后面的示例中讨论这种类型的安全功能。
java中的泛型与C++中的模板类似。例如,HashSet、ArrayList、HashMap等类很好地使用泛型。对于泛型类型,这两种方法有一些基本的区别。
Java泛型的类型
通用方法: 泛型Java方法接受一个参数,并在执行任务后返回一些值。它与普通函数完全相同,但是,泛型方法具有由实际类型引用的类型参数。这使得通用方法可以以更通用的方式使用。编译器负责安全类型,这使程序员能够轻松地编写代码,因为他们不必执行长时间的单独类型转换。
通用类: 泛型类的实现方式与非泛型类完全相同。唯一的区别是它包含一个类型参数部分。可以有多种类型的参数,用逗号分隔。接受一个或多个参数的类,被称为参数化类或参数化类型。
泛型类
和C++一样,我们使用< >来指定泛型类创建中的参数类型。要创建泛型类的对象,我们使用以下语法。
// To create an instance of generic class BaseType <Type> obj = new BaseType <Type>()
注: 在参数类型中,我们不能使用诸如“int”、“char”或“double”之类的原语。
JAVA
// 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()); } } |
15 GeeksForGeeks
我们还可以在泛型类中传递多个类型参数。
JAVA
// 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(); } } |
GfG 15
通用功能:
我们还可以编写泛型函数,根据传递给泛型方法的参数类型,使用不同类型的参数调用这些函数。编译器处理每个方法。
JAVA
// 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 ); } } |
java.lang.Integer = 11 java.lang.String = GeeksForGeeks java.lang.Double = 1.0
泛型仅适用于引用类型:
当我们声明泛型类型的实例时,传递给类型参数的类型参数必须是引用类型。我们不能使用像这样的原始数据类型 智力 , 烧焦
Test<int> obj = new Test<int>(20);
上面这一行导致编译时错误,可以使用类型包装器来封装基元类型来解决。
但是基元类型数组可以传递给type参数,因为数组是引用类型。
ArrayList<int[]> a = new ArrayList<>();
泛型类型因其类型参数而异:
考虑下面的java代码。
JAVA
// 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()); iObj = sObj; // This results an error } } |
输出:
error: incompatible types: Test cannot be converted to Test
尽管iObj和sObj属于类型测试,但它们是对不同类型的引用,因为它们的类型参数不同。泛型通过这一点增加了类型安全性,并防止了错误。
Java泛型中的类型参数
类型参数命名约定对于彻底学习泛型很重要。常见的类型参数如下所示:
- T型
- E-元素
- K–键
- N–数字
- V–价值
仿制药的优点:
与非泛型代码相比,使用泛型的程序有很多好处。
1.代码重用: 我们可以编写一次方法/类/接口,并将其用于我们想要的任何类型。
2.类型安全: 泛型会在编译时出现错误,而不是在运行时(最好在编译时了解代码中的问题,而不是让代码在运行时失败)。假设您想创建一个存储学生姓名的ArrayList,如果程序员错误地添加了一个整数对象而不是字符串,编译器会允许它。但是,当我们从ArrayList检索这些数据时,它会在运行时引发问题。
JAVA
// 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 ); } } |
输出:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at Test.main(Test.java:19)
泛型如何解决这个问题?
定义ArrayList时,我们可以指定此列表只能接受字符串对象。
JAVA
// Using Java Generics converts run time exceptions into // compile time exception. 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" ); // 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 ); } } |
输出:
15: error: no suitable method found for add(int) al.add(10); ^
3.不需要单独类型的铸件: 如果我们不使用泛型,那么在上面的示例中,每次从ArrayList检索数据时,我们都必须对其进行类型转换。每次检索操作中的打字都是一件令人头疼的事。如果我们已经知道我们的列表只包含字符串数据,那么我们不需要每次都对它进行类型转换。
JAVA
// 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 ); } } |
4. 泛型促进了代码的可重用性: 借助Java中的泛型,我们可以编写处理不同类型数据的代码。例如
public <T> void genericsMethod (T data) {...}
在这里,我们创建了一个泛型方法。同样的方法也可以用于对整型数据、字符串数据等执行操作。
5.实现通用算法: 通过使用泛型,我们可以实现适用于不同类型对象的算法,同时它们也是类型安全的。
本文由 达尔梅什·辛格 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以写一篇文章,然后将文章邮寄给评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。