Java 基础篇之泛型
2020-12-13 16:29
标签:eth 传递 cep rgs 处理 定义类 from 代码 声明 在没有泛型前,一旦把一个对象丢进集合中,集合就会忘记对象的类型,把所有的对象都当成 Object 类型处理。当程序从集合中取出对象后,就需要进行强制类型转换,这种转换很容易引起 ClassCastException 异常。 程序在创建集合时指定集合元素的类型。增加了泛型支持后的集合,可以记住集合中元素的类型,并可以在编译时检查集合中元素的类型,如果试图向集合中添加不满足类型要求的对象,编译器就会报错。 这个方法声明没有任何问题,但是调用该方法实际传入的参数值,可能会出错。考虑如下代码: 为了表示各种泛型 List 的父类,可以使用类型通配符。 现在传入任何类型的 List,程序可以正常打印集合 c 中的元素。 不过集合中元素的类型会被当成 Object 类型对待。 当使用 看如下代码: 下面代码将引起编译错误,因为 方法一:通过类型通配符解决,即 需要进行强制类型转换,因为 方法二:使用被限制的泛型通配符 在定义类型形参时设定类型通配符上限。以此来表示传递给该类型形参的实际类型必须是该上限类型或者其子类。 泛型方法就是在声明方法时定义一个或多个类型形参。多个类型参数之间用逗号隔开。 泛型方法解决了什么问题? 上面定义的方法没有任何问题,关键在于方法中的 c 形参,它的数据类型是 如果使用通配符 泛型方法。 进一步改造,如下 和泛型方法类似,Java 也允许在构造器签名中声明类型形参,这就产生了所谓的泛型构造器 实现一个方法,将 src 集合里的元素复制到 dest 集合里,且返回最后一个被复制的元素的功能。 因为 dest 集合可以保存 src 集合里的所有元素,所以 dest 集合元素的类型应该是 src 集合元素类型的父类。 为了表示两个参数间的类型依赖,考虑同时使用之前介绍过的通配符、泛型参数来实现该方法,代码如下: 上面的代码有一个问题,ln 的类型是 为了解决这个问题,引入通配符下限, 泛型基本上都是在编译器这个层次来实现的。在生成的 Java 字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数, 会被编译器在编译的时候去掉。这个过程就称为泛型擦除。如在代码中定义的 欢迎关注我的公众号 Java 基础篇之泛型 标签:eth 传递 cep rgs 处理 定义类 from 代码 声明 原文地址:https://www.cnblogs.com/Tianny/p/11620384.html背景
定义
示例
集合使用泛型
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DiamondTest {
public static void main(String[] args) {
List
类、接口使用泛型
public class Apple
类型通配符
需求分析
public void test(List
List
问题解决
List>
表示元素类型未知的 List。这个 ?
号被称为通配符,它可以匹配任何类型。将上面的代码,改为如下形式:public void test(List> c) {
for (int i = 0; i
类型通配符的上限
需求分析
List>
时,表明它可以是任何泛型 List 的父类。如果我们只希望它代表某一类泛型 List 的父类,java 提供了被限制的泛型通配符。public abstract class Shape {
public abstract void draw(Canvas c);
}
public class Circle extends Shape {
@Override
public void draw(Canvas c) {
System.out.println("在画布上" + c + "上画一个圆");
}
}
public class Rectangle extends Shape {
@Override
public void draw(Canvas c) {
System.out.println("把一个矩形画在画布" + c + "上");
}
}
import java.util.List;
public class Canvas {
public void drawAll(List
List
并不是 List
的子类型,所以不能把 List
对象当成 List
类用。// 错误示范
List
问题解决
List>
方式。
List>
中元素默认为 Object 类型import java.util.List;
public class Canvas {
public void drawAll(List> shapes) {
for (Object obj : shapes) {
Shape s = (Shape)obj // 但是需要进行强制类型转换,因为前面提到过 List> 中元素默认为 Object 类型
s.draw(this);
}
}
}
List extends Shape>
可以表示 List
和 List
的父类。只要 List 尖括号里的类型是 Shape 的子类即可。import java.util.List;
public class Canvas {
public void drawAll(List extends Shape> shapes) { // 使用被限制的泛型通配符
for (Shape s : shapes) {
s.draw(this);
}
}
}
形参类型上的应用
public class Apple
泛型方法
定义
修饰符
需求分析
static void fromArrayToCollection(Object[] a, Collection
Collection
。假设传入的实际参数的类型是 Collection
,因为 Collection
并不是 Collection
的子类,所以这个方法的功能非常有限,它只能将 Object[] 数组的元素复制到元素为 Object 类型(Object 的子类不行)的 Collection 集合中。Collection>
是否可行呢?显然也不行,Collection 集合提供的的 add() 方法中有类型参数 E,而如果使用类型通配符,这样程序无法确定 c 集合中的元素类型,所以无法正确调用 add 方法。问题解决
import java.util.ArrayList;
import java.util.Collection;
public class GenericMethodTest {
// 声明一个泛型方法
static
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class RightTest {
static
泛型构造器
public class Foo {
// 泛型构造器
public
类型通配符下限
需求分析
public static
List
,那么 T 的实际类型就是 Number,即返回值 last 类型是 Number 类型。但实际上最后一个复制元素的类型一定是 Integer。也就是说,程序在复制集合元素的过程中,丢失了 src 集合元素的类型。问题解决
super Type>
。表示必须是 Type 本身或者 Type 的父类。改写后的完整代码,如下:import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class MyUtils {
// 使用通配符下限
public static
泛型擦除
List
和 List
等类型, 在编译之后都会变成 List, JVM 看到的只是 List, 泛型附加的类型信息对 JVM 来说是不可见的。