泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。
在集合框架(Collection framework)中泛型的身影随处可见。例如,Map 类允许向一个 Map 类型的实例添加任意类的对象,即使最常见的情况在给定映射(map)中保存一个string键值对。
命名类型参数
对于常见的泛型模式,推荐的泛型类型变量:
大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦除,正确理解泛型概念的首要前提是理解类型擦除。Java 泛型是如何工作的?什么是类型擦除?答:泛型是通过类型擦除来实现的,编译器在编译时擦除了所有泛型类型相关的信息,所以在运行时不存在任何泛型类型相关的信息,譬如 List<Integer> 在运行时仅用一个 List 来表示,这样做的动机是兼容 Java 1.5 之前版本。
泛型擦除具体来说就是在编译成字节码时首先进行类型检查,然后进行类型擦除(即所有类型参数都用他们的限定类型替换,包括类、变量和方法),最后如果类型擦除和多态性发生冲突,就在子类中使用桥接方法解决;如果调用泛型方法的返回类型被擦除,则在调用该方法时插入强制类型转换。在类型擦除中,编译器确保不会创建额外的类,并且没有运行时开销。
类型擦除原则
<T> T 和T的区别:T是Type的首字母缩写;<T> T 表示“返回值”是一个泛型,传入什么类型,就返回什么类型;而单独的“T”表示限制传入的参数类型。
<T> T 的用法
这个<T> T 表示返回值T的类型是泛型,T是一个占位符,用来告诉编译器,这个东西是先给我留着, 等我编译的时候再告诉你是什么类型。
import org.springframework.util.CollectionUtils; import java.util.ArrayList; import java.util.List; public class Demo { public static void main(String[] args) { Demo demo = new Demo(); //获取string类型 List<String> array = new ArrayList<String>(); array.add("test"); array.add("doub"); String str = demo.getListFisrt(array); System.out.println(str); //获取Integer类型 List<Integer> nums = new ArrayList<Integer>(); nums.add(31); nums.add(32); Integer num = demo.getListFisrt(nums); System.out.println(num); } /** * 这个<T> T 可以传入任何类型的List * 关于参数T * 第一个 表示是泛型 * 第二个 表示返回的是T类型的数据 * 第三个 限制参数类型为T * * @param data * @return */ private <T> T getListFisrt(List<T> data) { if (CollectionUtils.isEmpty(data)) { return null; } return data.get(0); } }
T 的用法
单独的T表示限制参数的类型。这种用法一般多用于共同操作一个类对象,然后获取里面的集合信息。
import java.util.ArrayList; import java.util.List; public class Demo2<T> { public static void main(String[] args) { //限制T 为String 类型 Demo2<String> demo = new Demo2<String>(); List<String> array = new ArrayList<String>(); array.add("Tom"); array.add("河南"); String str = demo.getListFisrt(array); System.out.println(str); //获取Integer类型 Demo2<Integer> demo2 = new Demo2<Integer>(); List<Integer> nums = new ArrayList<Integer>(); nums.add(12); nums.add(13); Integer num = demo2.getListFisrt(nums); System.out.println(num); } /** * 这个只能传递T类型的数据 * 返回值 就是Demo<T> 实例化传递的对象类型 * * @param data * @return */ private T getListFisrt(List<T> data) { if (data == null || data.size() == 0) { return null; } return data.get(0); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
问题内容: 我想知道以下两个方法声明之间有什么区别: 有什么可以/可以做的,而不是另一种?我在本网站的其他地方找不到这个问题。 问题答案: 与上下文隔离-没有区别。在和两者上,您只能调用的方法。 但是有上下文-如果您有泛型类: 然后: 与对象相同的代码 两个优点: 无需强制转换(编译器向您隐藏了此内容) 编译有效的时间安全性。如果使用的是版本,则不能确保方法始终返回。如果返回,则在运行时会有一个。
我在学院有一些工作,我们必须按照给定的模块实现通用代码。 所以我正在创建一个只接受、、和的类 我看了一些关于泛型的youtube视频,也很理解,但我的代码中有一个问题,我在任何地方都找不到解决方案。 这是我的课: 在getResultAslong方法中,它应该采用长数据类型,但我有一个问题,即不能使用*操作数。问题是什么?
我正在尝试构建一个通用方法,该方法将调用任何特定于API的endpoint,每个endpoint都返回自己的对象类型。 以上操作不起作用(失败,出现空指针异常) 还尝试了这个: 这失败了: 我已经看到了一种可能的解决方案,通过传入所需类的虚拟对象,但这不是一个理想的选择,因为它需要添加类型参数并向下传递一长串调用。 不知道这将如何工作。
当然,这段代码不起作用。因为get()和set()方法。我可以用那样的东西吗?
我使用的是Azure.data.tables nuget包的12.0.0-beta.6。当我尝试调用TableClient.GetQueryAsync时,它会给出错误: “类型”T“必须是引用类型,才能将其用作泛型类型或方法”TableClient.GetEntityAsync(string,string,IEnumerable,CancellationToken)“中的参数”T“。” 我看不出我
目前,我使用这个解决方案,使用,而不是: