案例引入:
public class Point {
private Object x;
private Object y;
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public Object getY() {
return y;
}
public void setY(Object y) {
this.y = y;
}
public static void main(String[] args) {
Point point = new Point();
//自动装箱
point.setX(10.1);
point.setY(20.2);
//自动拆箱
//有一个风险,x和y都是相同的类型,如果用户不小心输入了不同的x和y的类型,那么在强转时就会发生错误
double x = (double)point.getX();
double y = (double)point.getY();
System.out.println("x = "+ x +",y = "+ y);
//换一种类型试一下
Point point1 = new Point();
point1.setX("东经101度");
point1.setY("北纬55度");
String x1 = (String)point1.getX();
String y1 = (String)point1.getX();
System.out.println("x= "+ x1 +", y ="+y1);
Point p2 = new Point();
p2.setX(10.1);
p2.setY("北纬20度");
String x3 = (String)point.getX();
String y3 = (String)point.getY();
System.out.println("x = "+ x3 +",y = "+y);
}
}
运行结果:
当x和y设置为不同的类型时,再进行强制类型转换,就会发生运行时异常(类型转换异常),强制发生的,这个错误是在编译期无法判断,可以正常编译,但不能运行出结果
1.泛型的基本使用:守门员,编译期检查类型是否正确
泛型是指在类定义时不会设置类中的属性或方法参数的具体类型,而是在类使用时(创建对象时)再进行类型的定义。
类声明后的<>中的这个T被称为类型参数,用于指代任意类型,实际上T只是个代表,写啥都可以。
表示此时value1,value2都是在类定义时没有明确类型,只有在引用时才告知编译器类型。
出于规范而言,类型参数用单个的大写字母来代替,常见的如下:
T:代表任意类
E:代表Element或是异常
K:和V搭配使用,Map< Integer,String>
以下体现了我们泛型的编译过程判断:
假设我们value1和value2的类型不同,可以设置两个泛型参数,在具体使用时,可以相同也可以不同。
泛型不光编译期就会校验类型以外,使用泛型不需要强制类型转换。
2.泛型方法
此处的泛型方法指的是有自己的类型参数
上面的不是泛型方法哦,只不过返回值或者参数使用了泛型变量而已,此时的T是泛型类的参数
如何验证test方法的T和MyClass的T是否是相同的参数类型? 不是
test的<T>表示此方法是个泛型方法,有一个类型参数<T>,不是返回值,只是告知编译器这是一个泛型的声明。
void是指test方法没有返回值。
看到<>,表示这是一个泛型的声明
泛型方法始终以自己的类型参数为准,和类中的类型参数无关。
为了避免混淆,一般定义泛型方法时,尽量避免使用类中已经使用过的泛型参数字母。
以下是一个标准的泛型方法:
3.泛型接口
子类在实现接口时有两种选择,保留泛型或定义子类时明确泛型
1>保留泛型
2>定义子类时明确泛型