泛型的使用
- 1.泛型的引入
- 2. 泛型的基本使用
- 2.1 泛型类
- 2.2 泛型方法
- 2.3 泛型方法和泛型类
1.泛型的引入
JDK1.5后引入泛型。
假如需要定义一个描述坐标的程序类Point,需要提供两个属性x,y。对于这两个属性的内容可能有如下选择:
- x = 10, y = 20
- x = 10.1, y = 20.1
- x = 东经80度, y = 北纬20度
因为Point中的x, y 属性有多种类型,所以采用Object去接收。
举例:定义一个Point类
//因为坐标可能是各种类型(Integer,Float,Double,String),
// 所以采用Object接收
public class Point1 {
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;
}
@Override
public String toString() {
return "Point1{" +
"x=" + x +
", y=" + y +
'}';
}
public static void main(String[] args) {
Point1 intPoint = new Point1();
intPoint.setX(20);
intPoint.setY(10); //10 ->Integer ->Object
System.out.println(intPoint);
Point1 strPoint = new Point1();
strPoint.setX("东经120度"); //String - >Object
strPoint.setY("北纬38度");
System.out.println(strPoint);
Point1 point1 = new Point1();
point1.setX(120);
point1.setY("北纬38度");
System.out.println(point1);
}
}
/**
Point1{x=20, y=10}
Point1{x=东经120度, y=北纬38度}
Point1{x=120, y=北纬38度}
*/
但是针对最后一个坐标,设置方把坐标内容设置成了Integer 和String 类型 ,但是接收方不知道,于是执行时候就会出现ClassCastException 比如下面的:
//接收方
Integer x = (Integer)point1.getX();
Integer y = (Integer) point1.getY();
或者在传参的时候,你不知道什么类型,也会运行时发生异常:
public static int[] getXY(Point1 point1){
Integer x = (Integer) point1.getX();
Integer y = (Integer) point1.getY();
return new int[]{x,y};
}
总结:
- 我们希望在编译时,及时发现类型不匹配问题,但使用Object接收时,发现不了
- 必须明确知道参数类型中的引用数据类型的具体类型Object
- 向下转型是,需要通过instanceof 判断
举例:对于上面的传参异常,可以使用instanceof进行判断
public static int[] getXY(Point1 point1){
Integer x = (Integer) point1.getX();
if((point1.getY())instanceof Integer){
Integer y = (Integer) point1.getY();
return new int[]{x,y};
}else {
throw new ClassCastException("y 不是Integer类型");
}
}
2. 泛型的基本使用
- 泛型指的就是在类定义的时候并不会设置 类中的属性和方法 中的具体参数类型 ,而是在类使用 的时候咋进行定义。
- 泛型类的基本语法:
class MyClass<T>{
T value;
}
- 其中
< >
中的T被称作是类型参数,用于指代任何类型。常见的有:
- T代表一般的任何类
- E代表Element的意思,或者Exception异常的意思
- K代表Key的意思
- V代表Value的意思,通常与K一起配合使用
- S代表Subtype的意思
2.1 泛型类
如果一个类被< >
定义,那么它就被称为泛型类
注意 :泛型值接收类,所有的基本数据类型必须使用包装类型
举例:使用泛型定义Point类
public class Point2<T> {
private T x;
private T y;
public void setX(T x) {
this.x = x;
}
public T getX(){
return x;
}
public void setY(T y) {
this.y = y;
}
public T getY() {
return y;
}
@Override
public String toString() {
return "Point2{" +
"x=" + x +
", y=" + y +
'}';
}
public static void main(String[] args) {
//JDK1.7后,泛型类型实例化对象构造方法<>不需要指定类型
Point2<String> point = new Point2<>();
point.setX("东经120度"); //此处setX中指定的是String类型
point.setY("北纬38度");
System.out.println(point);
//当使用泛型类的时候,决定属性的具体类型
Point2<Integer>point1 = new Point2<>();
point1.setX(20);
point1.setY(10);
System.out.println(point1);
}
}
另外,当使用泛型类之后,也避免了向下转型,这也就意味着安全隐患被消除 了。引入泛型后,如果明确设置了类型,则为设置类型;如果没有设置类型。则默认为Object。
举例:泛型类引入多个参数
public class Point3<T, E> {
private T x;
private E y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public E getY() {
return y;
}
public void setY(E y) {
this.y = y;
}
@Override
public String toString() {
return "Point3{" +
"x=" + x +
", y=" + y +
'}';
}
public static void main(String[] args) {
Point3<Integer,String> p1 = new Point3<>();
p1.setX(120);
p1.setY("北纬38度");
System.out.println(p1);
Point3<Integer,Integer> p2 = new Point3<>();
p2.setX(20);
p2.setY(10);
System.out.println(p2);
}
}
2.2 泛型方法
泛型不仅可以用于定义类,还可以单独定义方法。
举例:使用泛型方法
public class Point4 {
//只是针对方法中的参数,在方法的返回值前加上<T>
public <T> void print(T t){
System.out.println("泛型方法");
}
public static void main(String[] args) {
Point4 point4 = new Point4();
point4.print("hello");
point4.print(new Point());
point4.print(10);
}
}
2.3 泛型方法和泛型类
泛型方法可以和泛型类共存。
举例:泛型方法和泛型类共存
public class Point5<T, E> {
private T x;
private E y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public E getY() {
return y;
}
public void setY(E y) {
this.y = y;
}
public <T> void print(T t){
System.out.println("nonono");
}
@Override
public String toString() {
return "Point5{" +
"x=" + x +
", y=" + y +
'}';
}
public static void main(String[] args) {
Point5<Integer,String> p5 = new Point5<>();
p5.setX(120);
p5.setY("北纬38度");
System.out.println(p5);
p5.print("hello");
}
}
总结:
- 泛型类和泛型方法可以共存,二者各自独立
- 泛型方法始终以自己定义的类型参数为标准
- 为了避免混淆,如果一个泛型类中存在泛型方法,那么两者的参数最好不要同名