Java中泛型的基本使用

1.泛型的引入

JDK1.5后引入泛型。
假如需要定义一个描述坐标的程序类Point,需要提供两个属性x,y。对于这两个属性的内容可能有如下选择:

  1. x = 10, y = 20
  2. x = 10.1, y = 20.1
  3. 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度}
*/

但是针对最后一个坐标,设置方把坐标内容设置成了IntegerString 类型 ,但是接收方不知道,于是执行时候就会出现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};
    }

总结:

  1. 我们希望在编译时,及时发现类型不匹配问题,但使用Object接收时,发现不了
  2. 必须明确知道参数类型中的引用数据类型的具体类型Object
  3. 向下转型是,需要通过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");
    }
}

总结:

  • 泛型类和泛型方法可以共存,二者各自独立
  • 泛型方法始终以自己定义的类型参数为标准
  • 为了避免混淆,如果一个泛型类中存在泛型方法,那么两者的参数最好不要同名

猜你喜欢

转载自blog.csdn.net/mi_zhi_lu/article/details/90680789