Java泛型Generics​入门详解
  93byl95AX42O 2023年11月25日 67 0

Java泛型Generics

泛型基础知识

  • 泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。
  • 泛型的格式:<数据类型>
  • 注意:泛型只能支持引用数据类型。如果我们没有给集合指定类型,默认认为所有的数据类型都是Object类型,此时可以往集合中添加任意的数据类型。带来一个坏处是由于多态的存在,我们在获取数据的时候,无法使用他的特有行为。此时推出了泛型,可以在添加数据的时候就把类型进行统一。而且我们在获取数据的时候,也避免了强转,使用上非常的方便。
    泛型的优点
    ●统一数据类型。
    ●把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来。
    Java中的泛型是伪泛型,也即仅存在Java源码中,在编译后的.class文件中泛型信息将不复存在,这种行为称为泛型的擦除。
    泛型的注意点
  • 泛型中不能写基本数据类型
  • 指定泛型的具体类型后,传递数据时,可以传入该类类型或者其子类类型
  • 如果不写泛型,类型默认是Object

自定义泛型

泛型可以在很多地方进行定义。

  • 类后面 泛型类
  • 方法上面 泛型方法
  • 接口后面 泛型接口

泛型类

使用场景:当一个类中,某个变量的数据类型不确定时,就可以定义带有泛型的类

格式:

修饰符class类名<类型>{
}

举例:

public class ArrayList<E>{
}

创建该类对象时,E就确定类型。此处E可以理解为变量,但是不是用来记录数据的,而是记录数据的类型,一般可以写成:T、E、K、V等。

泛型方法

方法中形参类型不确定时,可以使用类名后面定义的泛型<E>

方法中形参类型不确定时

方案①:使用类名后面定义的泛型 所有方法都能用

方案②:在方法申明上定义自己的泛型 只有本方法能用

格式:

修饰符<类型> 返回值类型 方法名(类型变量名){
}

举例:

Public <T> void show(T t){
}

此处T可以理解为变量,但是不是用来记录数据的,而是记录类型的,可以写成:T、E、K、V等

如下代码中包含一个addAll方法,注意泛型占位符要放在修饰符的后面,本例中是static关键字后面。

import java.util.ArrayList;

public class ListUtil {
 private ListUtil(){}

 public static<E> void addAll(ArrayList<E> list, E e1, E e2, E e3, E e4, E e5){
 list.add(e1);
 list.add(e2);
 list.add(e3);
 list.add(e4);
 list.add(e5);
 }
}

泛型接口

格式:

修饰符interface接口名<类型>{
}

举例:

public interface List<E>{
}

泛型接口的重点是如何使用一个泛型接口。

  • 方式1:实现类给出具体类型
  • 方式2:实现类延续泛型,创建对象时再确定

如下:

class MyArrayList2 implements List<String>{

}

class MyArrayList2<E> implements List<E>{

}

泛型的通配符

泛型不具备继承性,但是数据具备继承性。如下代码method方法要求一个ArrayList<Object>类型的参数,而如果传入子类Date(Object是所有类型的父类)的对象列表则会报错。

import java.util.ArrayList;
import java.util.Date;

public class GenericsDemo {
 public static void main(String[] args) {
 ArrayList<Object> list = new ArrayList<>();
 ArrayList<Date> dlist = new ArrayList<>();

 method(dlist); // 报错。泛型不具备继承性,但是数据具备继承性。

 // 如果要让method方法不报错则应使用list包含Date对象
 // 则可以先向list对象中添加Date对象
 list.add(new Date());
 list.add(new Date());

 method(list); // 不会报错。体现出数据具备继承性
 }

 public static void method(ArrayList<Object> l){

 }
}

有时候类或方法虽然不确定类型,但是希望只能传递具有继承关系的一类类型时,我们就可以使用泛型的通配符

?也表示不确定的类型可以进行类型的限定

  • ?: 与字符占位符一样,单独用表示所有类型
  • ? extends E:表示可以传递E或者E所有的子类类型
  • ? super E:表示可以传递E或者E所有的父类类型

应用场景

1.如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。

2.如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以泛型的通配符泛型的通配符

关键点:可以限定类型的范围。

import java.util.ArrayList;

public class GenericsDemo2 {

 public static void main(String[] args) {
 
 }

 public static void method1(ArrayList<?> p){ // 直接使用?时不用在修饰符后的尖括号类声明?问号

 }

 public static void method2(ArrayList<? extends Ye> p){

 }

 public static void method3(ArrayList<? super Fu> p){

 }
}

// 爷爷类
class Ye{}
// 父亲类
class Fu extends Ye{}
// 儿子类
class Zi extends Fu{}


综合练习

需求:

定义一个继承结构:

Java泛型Generics​入门详解_数据类型


属性:名字,年龄

行为:吃东西

波斯猫方法体打印:一只叫做XXX的,X岁的波斯猫,正在吃小饼干

狸花猫方法体打印:一只叫做XXX的,X岁的狸花猫,正在吃鱼

泰迪方法体打印:一只叫做XXX的,X岁的泰迪,正在吃骨头,边吃边蹭

哈士奇方法体打印:一只叫做XXX的,X岁的哈士奇,正在吃骨头,边吃边拆家

测试类中定义一个方法用于饲养动物

public static void keepPet(ArrayList<???>list){
//遍历集合,调用动物的eat方法
}

要求1:该方法能养所有品种的猫,但是不能养狗

要求2:该方法能养所有品种的狗,但是不能养猫

要求3:该方法能养所有的动物,但是不能传递其他类型


import java.util.ArrayList;
import java.util.Iterator;

public class TestMain {
 public static void main(String[] args) {
 Cat c1 = new LihuaCat();
 }

 // 需求1
 public static void keepPet1(ArrayList<? extends Cat> cats){
 Iterator<? extends Cat> citer = cats.iterator();
 while (citer.hasNext()){
 citer.next().eat();
 }
 }


 // 需求2
 public static void keepPet2(ArrayList<? extends Dog> dogs){
 Iterator<? extends Dog> citer = dogs.iterator();
 while (citer.hasNext()){
 citer.next().eat();
 }
 }

 // 需求3
 public static void keepPet3(ArrayList<? extends Animal> animals){
 Iterator<? extends Animal> citer = animals.iterator();
 while (citer.hasNext()){
 citer.next().eat();
 }
 }
}

泛型小结

1.什么是泛型?

JDK5引入的特性,可以在编译阶段约束操作的数据类型,并进行检查

2.泛型的好处?

●统一数据类型

●把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来。

3.泛型的细节?

●泛型中不能写基本数据类型

●指定泛型的具体类型后,传递数据时,可以传入该类型和他的子类类型

●如果不写泛型,类型默认是Object

4.哪里定义泛型?

●泛型类:在类名后面定义泛型,创建该类对象的时候,确定类型

●泛型方法:在修饰符后面定义方法,调用该方法的时候,确定类型

●泛型接口:在接口名后面定义泛型,实现类确定类型,实现类延续泛型

5.泛型的继承和通配符

●泛型不具备继承性,但是数据具备继承性

●泛型的通配符:?

? extend E

? super E

6.使用场景

●定义类、方法、接口的时候,如果类型不确定,就可以定义泛型

●如果类型不确定,但是能知道是哪个继承体系中的,可以使用泛型的通配符










【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月25日 0

暂无评论

推荐阅读
  anLrwkgbyYZS   2023年12月30日   28   0   0 i++iosi++ioscici
  anLrwkgbyYZS   2023年12月30日   33   0   0 ideciciMaxideMax
93byl95AX42O