泛型:让一个类/一个方法支持不同的数据类型。
为什么引入泛型
在Java中,为了方便接收参数类型的统一,提供了一个核心类object,利用此类对象可以接受所有类型的数据(包括基本数据类型与引用数据类型),但是由于其所描述的范围过大,所有在实际使用中就会出现传入数据类型错误,从而引发classCastException。
假如我们要设计可以描述坐标点的类Point(包括x与y坐标的信息),对于坐标点允许保留3
类数据
- 整型数据:x=10,y=10;
- 浮点型数据 x=10.1,y=20.9
- 字符串型数据 x=东经120°,y=北纬30°
于是设计Point类的时候,要考虑x与y属性的具体类型,这个类型要求可以保存3中数据
最原始的做法:利用Object类进行定义 - 整型数据 :基本数据类型 ----包装类Integer类对象-----自动向上转型为Object
- 浮点型数据: 基本数据类型 —包装类为double类对象----自动向上转型为Object
- 字符串型数据:String类对象--------------------------------------自动向上转型为Object
定义Point坐标点类
public class Point {
private Object x;
private Object y;
public void setX(Object x){
this.x=x;
}
public void setY(Object Y){
this.y=y;
}
public Object getX(){
return this.x;
}
public Object getY() {
return y;
}
}
Point类中x与y属性都采用了object作为存储类型,这样可以接受任意类型的数据类型,于是产生两种情况
情况1;使用者按照统一的数据类型设置坐标类型,并采用向下转型获取坐标的原始数据
public class Javademo {
public static void main(String[] args) {
Point point=new Point();
//所有数据通过object接受
point.setX(10);
point.setY(20);
//从里面获取数据,由于返回的数据是Object类型,所以必须进行强制向下转型
int x=(Integer) point.getX();
int y=(Integer) point.getY();
System.out.println("x坐标"+x+".y坐标"+y);
}
}
情况二:使用者没有按照统一的数据类型设置坐标内容,读取时进行错误的类型进行强制转换
public class Javademo {
public static void main(String[] args) {
Point point=new Point();
//所有数据通过object接受
point.setX(10);
point.setY("北纬10度");//与x坐标数据设置的不一样,但符合语法标准,在程序编译的时候没法发现问题
//从里面获取数据,由于返回的数据是Object类型,所以必须进行强制向下转型
int x=(Integer) point.getX();
int y=(Integer) point.getY();//在程序执行时,会发classCastException异常
System.out.println("x坐标"+x+".y坐标"+y);
}
}
由于在设置Point类做表的时候采用了不同的数据类型,所以在获取原始数据信息的时候就会出现程序运行异常。原因是Object接受的数据范围过大。
使用泛型
如果先要解决项目中可能出现的ClassCatException安全隐含,最核心的方法是避免强制进行对象向下转型操作。所以反向涉及的核心思想:类中枢性或者方法的参数与返回值类型采用动态标记,在对象实例化的时候动态配置要使用的数据类型。
public class Point<T> {
private Object x;
private Object y;
public void setX(Object x){
this.x=x;
}
public void setY(Object y){
this.y=y;
}
public Object getX(){
return this.x;
}
public Object getY() {
return this.y;
}
}
package java42_0125;
public class Javademo {
public static void main(String[] args) {
//实例化Point类对象,设置泛型标记T的目标来兴,属性、方法参数、返回值的类型
Point<Integer> point=new Point<>();
//所有数据通过object接受
point.setX(10);
point.setY(20);//与x坐标数据设置的不一样,但符合语法标准,在程序编译的时候没法发现问题
//从里面获取数据,由于返回的数据是Object类型,所以必须进行强制向下转型
int x=(Integer) point.getX();
int y=(Integer) point.getY();//在程序执行时,会发classCastException异常
System.out.println("x坐标"+x+".y坐标"+y);
}
}
在本程序中实例化Point类对象时所采用的的泛型设置为Integer,这样Point对象中x,y的类型是Integer,对应方法的参数和返回值类型也是Integer,这样在编译的时候明确知道了数据类型的错误,也避免了对象向下转型的错误
定义
class 类名称<类型形参列表> {
// 这里可以使用类型参数
}
- 类名后面加上泛型参数。<>表示当前这个类是泛型类
- E相当于是个形参,E表示某种具体的类型,会在实例化的时候确定E具体是哪种类型
- E必须是引用类型,如果需要内置类型,就需要使用对应的包装类。
java的类型只能呢个是引用类型,如果是内置类型,换成对应的包装类
实例化
实例化泛型类的时候,就需要显示的告诉实例对应的泛型参数是啥类型
类型边界
定义泛型类的时候,对未来实例化的时候能传入的类型实参做出限制
泛型参数这里的类型不应该随便填,要根据实际情况作出一些约束和校验