博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 泛型理解
阅读量:4094 次
发布时间:2019-05-25

本文共 3719 字,大约阅读时间需要 12 分钟。

1、泛型的引出

如果要实现对于不同数据类型的数据进行相同的操作时,C++使用模板,Java使用泛型。Java泛型多用于定义函数库,一般开发人员只需要可以看懂即可。


假如我们现在要定义一个类来表示坐标,要求坐标的数据类型可以是整数、小数和字符串,例如:

x = 10、y = 10x = 12.88、y = 129.65x = "东经180度"、y = "北纬210度"

方法一:借助方法重载、自动装箱和向上转型

针对不同的数据类型,除了借助方法重载,还可以借助自动装箱和向上转型。我们知道,基本数据类型可以自动装箱,被转换成对应的包装类;Object 是所有类的祖先类,任何一个类的实例都可以向上转型为 Object 类型,例如:

int --> Integer --> Objectdouble -->Double --> ObjectString --> Object

这样可以通过定义一个方法来实现不同数据类型的数据进行相同操作,如下:

class Point{    Object x = 0;    Object y = 0;    public Object getX() {        return x;    }    public Object getY() {        return y;    }    public void setX(Object x) {        this.x = x;    }    public void setY(Object y) {        this.y = y;    }}public class Demo {    public static void main(String[] args){        Point p = new Point();        p.setX(10);  // int -> Integer -> Object        p.setY(20);        int x = (Integer)p.getX();  // 必须向下转型 Object -> Integer        int y = (Integer)p.getY();        System.out.println("This point is:" + x + ", " + y);        p.setX(25.4);  // double -> Integer -> Object        p.setY("东经180度");        double m = (Double)p.getX();  // 必须向下转型  Object -> Double    double n = (Double)p.getY();         // 运行期间此语句抛出异常       //java.lang.ClassCastException 两个没有什么关系的类进行转化时,会出现这样类型不匹配的错误。         System.out.println("This point is:" + m + ", " + n);    }}

向上转型的核心目的在于统一操作的参数,而向下转型的目的是操作子类的对象,向下转型是一件非常不安全的操作,如果操作不当就会报错:java.lang.ClassCastException 。

方法二:使用泛型

从JDK1.5之后增加了泛型技术,核心在于:类在定义的时候可以定义一个表示类型的标记,来表示类中属性或方法参数的类型,在使用的时候动态的定义具体的数据类型。

class Point
{ private T x = 0; private T y = 0; public T getX() { return x; } public T getY() { return y; } public void setX(T x) { this.x = x; } public void setY(T y) { this.y = y; } public int is_equal() { if(this.x == this.y) return 0; else return -1; }}public class Demo { public static void main(String[] args){ // 定义数据,将泛型具体定义为Integer类 Point
p = new Point
(); // 设置数据,此时成员函数setX()、setY()的参数类型自动为Integer p.setX(10); p.setY(20); // 取数据,此时成员函数getX()、getY()的返回值类型自动变为Integer int x = p.getX(); int y = p.getY(); System.out.println("This point is:" + x + ", " + y); //实例化对象时,泛型具体定义为Sting类的例子: Point
q = new Point
(); p.setX("东经180度"); p.setY("北纬210度"); String m = p.getX(); String n = p.getY(); System.out.println("This point is:" + m + ", " + n); }}

使用泛型后,所有类中属性都是动态设置(对于返回类型固定的成员方法,可以在定义类的时候设置返回类型,不受泛型的制约,例如上述例子中,在类中定义的is_equal()方法),避免了向下转型的问题,从而解决了类转换的安全隐患。

需要注意的是:

  1. 使用泛型的时候,那么泛型具体化时能够使用的类型只能是引用类型(Intege、Double….),不能是基本数据类型(int、double….)。
  2. 使用泛型类或者接口,没有设置泛型的具体类型,那么会出现编译时的警告,为了保证程序不出错,将使用Object类型来描述此泛型,退化为方法一。
  3. JDK1.7之后,泛型可以简化声明。 Point p = new Point<>() ; //实例化的泛型可以省略

2、通配符 ?


如果已经定义了泛型类,在类外定义方法并且需要使用泛型类型作为参数时,不能够确定当前参数具体类型,此时需要有一种方式可以接受任意的一种泛型类型。


方法一:参数中去掉泛型符号

class Message
{public T a; } public static void fun (Message temp) { } 由于,去掉了泛型符号,此方法默认的Message类型为Object,可以在fun中对temp的成员a进行任意类型的更改,例如: public static void fun (Message temp) { temp.a = "no matter what type you are , i am a string";}

方法二: 使用通配符?

class Message
{ public T a; } public static void fun (Message
temp) { }使用通配符可以达到上述要求,并且满足在方法中只可以取出数据,而不可以修改数据。 public static void fun (Message
temp) { temp.a = "no matter what type you are , i am a string"; //报错 }

如果继续使用方法一的方式企图在方法中修改成员变量,则出现

The method Setx(capture#1-of ?) in the type Point<>capture#1-of ? is not applicable for the arguments (String)

其他通配符

? extends 类:设置泛型上限,可以在声明上和方法参数上使用;

? super 类:设置泛型下限,可以在方法参数上使用。

通过设置上下限,可以实现对于泛型类型的控制,使其类型具体化时受到一定的限制。

转载地址:http://nntii.baihongyu.com/

你可能感兴趣的文章
Koa 2 初体验(二)
查看>>
Koa2框架原理解析和实现
查看>>
vue源码系列文章good
查看>>
你不知道的Virtual DOM
查看>>
VUE面试题总结
查看>>
写好JavaScript条件语句的5条守则
查看>>
原生JS中DOM节点相关API合集
查看>>
【TINY4412】U-BOOT移植笔记:(7)SDRAM驱动
查看>>
【TINY4412】U-BOOT移植笔记:(12)BEEP驱动
查看>>
单链表的修改和删除
查看>>
C++的三个基本特征:封装、继承、多态
查看>>
C++虚函数的总结
查看>>
什么是URL地址?
查看>>
C++多态的实现方式总结
查看>>
学习C++需要注意的问题
查看>>
C++模板
查看>>
C++双冒号(::)的用法
查看>>
【Unity】封装SQLite管理类
查看>>
【Unity】面试题整理
查看>>
【C#】如何实现一个迭代器
查看>>