Java进阶知识,轻松理解Java泛型

在学习泛型之前我们先回顾下JAVA的数据类型以及涉及到的一些概念 。
Java数据类型
Java的两大数据类型分为基础类型和引用类型 。基本类型的数值不是对象 , 不能调用对象的toString()、hashCode()、getClass()、equals()等方法 。

Java进阶知识,轻松理解Java泛型

文章插图
 
自动装箱
把基本类型用它们对应的引用类型包装起来 , 使它们具有对象的特质 , 可以调用toString()、hashCode()、getClass()、equals()等方法 。
例如:
//自动装箱Integer i=1;而实际上编译器会调用static Integer valueOf(int i)这个方法 , 返回一个表示指定int值的Integer对象 。Integer i=1; ->. Integer i=Integer.valueOf(1);
拆箱
跟自动装箱的方向相反 , 将引用类型转换为基本类型 。
//拆箱int i = new Integer(1);自动装箱和拆箱是由编译器来完成的 , 编译器会在编译期根据语法决定是否进行装箱和拆箱动作 。
假如我们定义一个类来表示坐标 , 要求类中基础类型可以为整数 、小数、字符串 , 例如:
Object x=116,y=54;Object x=116.92,y=54.31;Object x="经度116.92",y="纬度54.31";【Java进阶知识,轻松理解Java泛型】我们知道 , 基本数据类型可以自动装箱 , 被转换成对应的包装类 。Object 是所有类的祖先类 , 任何一个类的实例都可以向上转型为 Object 类型 , 例如:
int -> Integer -> Objectdouble -> Double -> ObjectString -> Object泛型的使用
Java进阶知识,轻松理解Java泛型

文章插图
 
如果要取出坐标值就需要向下转型 , 向下转型存在着风险 , 而且编译期间不容易发现 , 只有在运行期间才会抛出异常 , 所以要尽量避免使用向下转型 。例如下面的实例:
public class Test {public static void main(String[] args){Point point = new Point();//int -> Integer -> Objectpoint.setX(116);point.setY(54);//向下转型int x = (Integer) point.getX();int y = (Integer) point.getY();System.out.println("Point :x="+x+" y="+y);//double -> Double -> Objectpoint.setX(116.92);point.setY("纬度54.32");//向下转型Double x1 = (Double) point.getX();//会抛出ClassCastException异常Double y1 = (Double) point.getY();System.out.println("Point :x1="+x1+" y1="+y1);}}class Point{Object x = null;Object y = null;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;}}那么Java中如何避免这样的情况发生呢?
Java中泛型出现就是解决出现这样的问题 , 所谓的“泛型”就是任意的数据类型 。以下代码将利用泛型解决上面的问题 。
public class Test {public static void main(String[] args){//实例化泛型Point<Integer,Integer> point = new Point<Integer,Integer>();point.setX(116);point.setY(54);int x = point.getX();int y =point.getY();System.out.println("Point :x="+x+" y="+y);Point<Double,String> point1 = new Point<Double,String>();point1.setX(116.92);point1.setY("纬度54.32");Double x1 =point1.getX();String y1 = point1.getY();System.out.println("Point :x1="+x1+" y1="+y1);}}//定义泛型类class Point<T1,T2>{T1 x = null;T2 y = null;public T2 getY() {return y;}public void setY(T2 y) {this.y = y;}public T1 getX() {return x;}public void setX(T1 x) {this.x = x;}}实例中的T1和T2叫类型参数 , 类型参数是用来表示自定义标识符 , 用来传递数据的类型 。Java中传值参数用小括号包围 , 泛型参数用尖括号包围 , 多个参数用逗号间隔 , 例如:
<T>或<T , E>类型参数需要在类名后面给出 。一旦给出了类型参数 , 就可以在类中使用了 。类型参数必须是一个合法的标识符 , 习惯上使用单个大写字母 , 通常情况下 , K 表示键 , V 表示值 , E 表示异常或错误 , T 表示一般意义上的数据类型 。
泛型类在实例化时必须指出具体的类型 , 也就是向类型参数传值 , 格式为:
className variable<dataType1, dataType2> = new className<dataType1, dataType2>();也可以省略等号右边的数据类型 , 但是会产生警告 , 即:


推荐阅读