本文共 3719 字,大约阅读时间需要 12 分钟。
如果要实现对于不同数据类型的数据进行相同的操作时,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()方法),避免了向下转型的问题,从而解决了类转换的安全隐患。
需要注意的是:如果已经定义了泛型类,在类外定义方法并且需要使用泛型类型作为参数时,不能够确定当前参数具体类型,此时需要有一种方式可以接受任意的一种泛型类型。
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/