Java中的泛型

仿制药 方法 参数类型 其思想是允许类型(整数、字符串等,以及用户定义的类型)成为方法、类和接口的参数。使用泛型,可以创建使用不同数据类型的类。在参数化类型上操作的类、接口或方法等实体是泛型实体。

null

为什么是仿制药?

这个 对象 是所有其他类的超类,对象引用可以引用任何对象。这些特性缺乏类型安全性。仿制药增加了这种类型的安全功能。我们将在后面的示例中讨论这种类型的安全功能。

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主页上,并帮助其他极客。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享