JavaSE——面向对象高级三(5/5)-泛型方法、泛型的通配符、泛型擦除和注意事项

简介: JavaSE——面向对象高级三(5/5)-泛型方法、泛型的通配符、泛型擦除和注意事项

泛型方法

修饰符 <类型变量,类型变量,...> 返回值类型 方法名(形参列表){

}

public static <T> void test(T t){
 
}

注意:下面这种不是泛型方法

1. public E get(int index){
2. return (E) arr[index];
3. }

具体体现:

public class Test{
    public static void main(String[] args){
        test(new Dog()); //假设传入了狗对象
    }
    
    //泛型方法
    public static <T> T test(T t){  //返回值类型也为T类型
        return t;
    }
}

泛型的通配符

来看一个需求:所有汽车一起参加比赛,需要汽车类、具体的汽车品牌类,然后设计方法只能让汽车一起比赛。

现在假设已经定义了Car、BMW、BENZ类。

第一种情况:(定义总体的汽车集合,将各种汽车都放进这个集合里面)

public class Test{
    public static void main(String[] args){
        ArrayList<Car> cars = new ArrayList<>(); //创建一个汽车集合
        
        //我们可以将一辆奔驰和宝马放进这个汽车集合里面
        cars.add(new BMW());
        cars.add(new BENZ());
        //然后调用比赛的函数,没有什么问题
        go(cars);
    }
 
    public static void go(ArrayList<Car> cars){
    }
}

第二种情况:(定义不同的具体汽车集合,例如宝马车为一个集合,奔驰车为一个集合)

public class Test{
    public static void main(String[] args){
        ArrayList<Car> cars = new ArrayList<>(); //创建一个汽车集合
        
        ArrayList<BMW> bmws = new ArrayList<>(); //创建宝马车集合
        bmws.add(new BMW());
        bmws.add(new BMW()); //加入两辆宝马进入这个集合
 
        ArrayList<BENZ> benzs = new ArrayList<>(); //创建奔驰车集合
        benzs.add(new BENZ());
        benzs.add(new BENZ()); //同样加入两辆奔驰进入这个集合
 
        //此时调用比赛方法
        go(bmws);
        go(benzs); 
        //会发现报错,无法调用,数据类型不一样
    }
 
    public static void go(ArrayList<Car> cars){
    }
}

此时的ArrayList<BMW>和ArrayList<BENZ>其实和ArrayList<Car>已经没有关系了,或者说不算作是同一个数据类型了,所以无法调用传参为ArrayList<Car>的go方法。

所以就需要用到泛型方法了

对go方法进行修改:

public static <T> void go(ArrayList<T> cars){
 
}

但这个还是存在问题的,比如这个方法不仅宝马、奔驰对象可以加入,其他一些对象,比如狗(Dog)对象也可以加入;这就不符合我们的需求了。所以再稍加修改:

public static <T extends Car> void go(ArrayList<T> cars){
 
}

这就是我们限定了T能接受的类型,它只能是Car类或者是Car的子类;Dog类和其他不是Car的子类的就会被踢出去了 。

这样其实就可以满足这个需求了。

接着我们就可以引入我们的通配符知识点了

我们看这里ArrayList<T>它自己就是一个泛型类,而前面又再定义了一个泛型方法,这是没有没有必要的,Java中提供了一种方案,让我们可以解决这个问题,也就是通配符

 通配符,在使用泛型的时候可以代表一切类型

public static void go(ArrayList<? extends Car> cars){
 
}

我们在定义泛型的时候一般用E、T、K、V......但是我们使用泛型的时候,就可以用“?”来表示一切类型,这里“? extends Car”的意思就是:可以传入一切是Car或者Car子类的类型。


这种写法称为上限技术,顾名思义Car类就是它最高可以传入的类型了;与其相反的就是下限技术:(用得稍微少一点)

public static void go(ArrayList<? super Car> cars){
 
}

也就是最低也要传入Car类,往上就是Car的父类。


小结

通配符

  • 就是“?”,可以在“使用泛型”的时候代表一切类型;E T K V是在定义泛型的时候使用。

泛型的上下限

  • 泛型上限:? extends Car :?能接收的必须是Car或者其子类。
  • 泛型下限:? super Car:?能接收的必须是Car或者其父类。

泛型擦除和注意事项

泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中就不存在泛型了,这就是泛型擦除。

泛型不支持基本数据类型,只能支持对象类型(引用数据类型)。

关于泛型擦除,我们要使用Java的反编译工具XJad来查看,


我们自己编写的代码在编译成class文件之后,泛型的数据类型都恢复成Object的了,底层会自己强转类型。也就是擦除了泛型。

第二点,泛型不支持基本数据类型,比如int、double,都是不支持的。

如果你非要使用基本数据类型,可以使用int类型的对象类型 Integer ,以及double类型的对象类型Double,例如:

public class Test{
    public static void main(String[] args){    
        //ArrayList<int> list1 = new ArrayList<>();
        //ArrayList<double> list1 = new ArrayList<>(); //都会报错
        
        //使用他们的对象类型就不会报错了
        ArrayList<Integer> list1 = new ArrayList<>();
        ArrayList<Double> list1 = new ArrayList<>();
    }
}

关于这些对象类型,接下来的文章会再详细了解。


至此,面向对象最核心的语法知识就全部学完了,接下来Java的学习,就是拿着这些语法知识去学习一个一个的API,API掌握得越多,Java的编程能力相对来说也就更强了,关于API的学习,前面我们学习过一些,接下来将更深入、更多地去学习。



END



目录
相关文章
|
7月前
|
存储 Java fastjson
Java泛型-4(类型擦除后如何获取泛型参数)
Java泛型-4(类型擦除后如何获取泛型参数)
95 1
|
6月前
|
Java
JavaSE——面向对象高级三(4/5)-认识泛型、定义泛型类、定义泛型接口
JavaSE——面向对象高级三(4/5)-认识泛型、定义泛型类、定义泛型接口
42 0
|
7月前
|
Java 编译器
[java进阶]——泛型类、泛型方法、泛型接口、泛型的通配符
[java进阶]——泛型类、泛型方法、泛型接口、泛型的通配符
|
7月前
|
存储
泛型进阶: 泛型方法 & 通配符
泛型进阶: 泛型方法 & 通配符
|
7月前
|
Java Go
【Java 泛型方法】泛型方法的定义和使用,泛型的通配符和泛型的上下限,泛型的注意事项
【Java 泛型方法】泛型方法的定义和使用,泛型的通配符和泛型的上下限,泛型的注意事项
|
7月前
|
设计模式 安全 Java
详解Java中的泛型(泛型的语法,擦除机制,泛型的上界)
详解Java中的泛型(泛型的语法,擦除机制,泛型的上界)
116 0
|
安全 Java 编译器
「 Java基础-泛型 」一篇文章说清楚Java泛型中的通配符T、E、K、V、N、?和Object的区别与含义
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型。 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。 可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。
「 Java基础-泛型 」一篇文章说清楚Java泛型中的通配符T、E、K、V、N、?和Object的区别与含义
|
安全 Java 容器
Java泛型(1)--集合使用泛型Generic、自定义泛型、泛型在继承上的体现、通配符的使用
Java泛型(1)--集合使用泛型Generic、自定义泛型、泛型在继承上的体现、通配符的使用
177 0
Java泛型(1)--集合使用泛型Generic、自定义泛型、泛型在继承上的体现、通配符的使用
|
安全 Java
Java泛型03:通配符的使用和泛型的继承
Java泛型03:通配符的使用和泛型的继承
231 0
Java泛型03:通配符的使用和泛型的继承
|
安全 Java
Java中泛型概述、泛型方法、泛型接口、类型通配符及可变参数的使用
泛型概述、泛型方法、泛型接口、类型通配符及可变参数的使用的简单示例
149 0