Java 泛型技术产生的原因:
package cn.mldn.utli; class Point { private Object x ; private Object y ; public void setX( Object x ) { this.x = x ; } public void setY( Object y ) { this.y = y ; } public Object getX() { return x ; } public Object getY() { return y ; } } public class TestDemo { public static void main(String[] args) { Point p = new Point() ; p.setX(10); p.setY(20); int x = (Integer) p.getX(); int y = (Integer) p.getY(); System.out.println(x + y) ; } }
上述的程序中,利用Point类存储整型数据,利用Object对象进行存储,向下转型为int型
public class TestDemo { public static void main(String[] args) { Point p = new Point() ; p.setX(10.1); p.setY(20.2); double x = (Double) p.getX(); double y = (Double) p.getY(); System.out.println(x + y) ; } }
上述代码则是利用Point类存储小数,利用Object对象进行存储,向下转型为Double型
public class TestDemo { public static void main(String[] args) { Point p = new Point() ; p.setX("上海"); p.setY("南京"); String x = (String) p.getX(); String y = (String) p.getY(); System.out.println(x + y) ; } }
上述代码则是利用Point类存储String数据内容,利用Object对象进行存储,向下转型为String型
————————————————
上述的三段代码,均利用Point类进行三种不同类型的多类型同对象的存储,而Point类中是利用Object进行存储的,于是可以在调用处通过向下转型的方式将Object转为int/double/String等类型数据(装箱/拆箱)。
泛型技术:类在定义的时候可以只用一个标记,此标记表示类中属性或方法参数的类型标记,在使用的时候才动态的设置:
package cn.mldn.utli; // 此时设置的T在Point定义上只表示一个标记,在使用的时候需要为其设置具体额类型 class Point<T> { // Type = T , 是一个类型 private T x ; // x的属性类型不明,有Point在使用时动态使用 private T y ; public void setX( T x ) { this.x = x ; } public void setY( T y ) { this.y = y ; } public T getX() { return x ; } public T getY() { return y ; } }
在使用Point类的时候才取设置的内容,也就是设置了类中属性的类型;
public class TestDemo { public static void main(String[] args) { Point<String> p = new Point<String>() ;
// 利用的就是包装类的自动装箱功能 p.setX("上海"); p.setY("南京"); // 由于泛型的特性,使用的时候动态的设置Point接收的类型为String类型,所以返回的也是String类型就不用在转型了 String x = p.getX(); String y = p.getY(); System.out.println(x + y) ; } }
使用泛型之后,所有类中属性的类型都是动态设置的,而所有使用泛型标记的方法参数类型也都是会发生改变。由此避免了向下转型的安全问题隐患。
如果是采用泛型,那么它能够接受的数据类型只能是基本数据类型的包装类表示,不可以引用类型!
# 在使用泛型类或者接口的时候,没有设置泛型的具体类型,会报错。(如果在没有设置泛型的具体类型的时候,所有泛型使用Object描述泛型的数据类型)
# 在JDK1.7后可以简化泛型:可以将实例化的泛型具体类型的定义省略
——————————
泛型通配符:
package cn.mldn.utli; class Message<T> { private T msg ; public void setMsg(T msg) { this.msg = msg ; } public T getMsg() { return msg ; } } public class TestDemo { public static void main(String[] args) { Message<String> m = new Message<> (); m.setMsg("Hello World!"); fun(m) ; // 引用传递 } public static void fun(Message<String> temp) { System.out.println(temp.getMsg()) ; } }
上述代码为Message类设置的是一个String的泛型对象;
如果我们需要一个可以接收任何类型的泛型数据,则可以使用 “?” 符号代替 "<>" 定义类型;如此以来则可以接收任何的泛型,但是不可以更改,只可以取出。
public class TestDemo { public static void main(String[] args) { Message<String> m = new Message<> (); m.setMsg("Hello World!"); fun(m) ; // 引用传递 } public static void fun(Message<?> temp) { System.out.println(temp.getMsg()) ; } }
在 “?”的通配符上 还有两个子通配符:
~ ? extends 类:设置泛型上限,可以在泛型声明上和方法参数上使用;
|-- ? extends Number : 意味着可以设置Number或者子类的泛型
~ ? super 类: 设置泛型的下限,方法参数上使用;
|-- ?super String : 意味只能设置String或者它的父类(Object)
泛型接口:
定义泛型接口
interface Message<T> { //设置泛型接口 public void print(T t) ; }
在接口上定义其相应的子类,定义子类主要有两种形式:
形式一:在子类上继续设置泛型
package cn.mldn.utli; interface Message<T> { //设置泛型接口 public void print(T t) ; } class MessageImpl<T> implements Message<T> { public void print(T t) { System.out.println(t) ; } } public class TestDemo { public static void main(String[] args) { Message<String> msg = new MessageImpl<String>() ; // 向上转型实例化 msg.print("Hello World!"); } }
形式二:在子类不设置泛型,而父接口明确定义一个泛型类型
package cn.mldn.utli; interface Message<T> { //设置泛型接口 public void print(T t) ; } class MessageImpl implements Message<String> { // 接口泛型的第二种定义方法,直接在实现接口的接口处明确一个泛型类型;由此实例化的时候不用设置泛型的具体类型 public void print(String t) { System.out.println(t); } } public class TestDemo { public static void main(String[] args) { Message msg = new MessageImpl() ; // 向上转型实例化 msg.print("Hello World!"); } }
-------------------------------
泛型方法:
泛型方法不一定定义在支持泛型的类中。
泛型方法的定义:
package cn.mldn.utli; public class TestDemo { public static void main(String[] args) { String str = fun("Hello,World!") ; System.out.println(str); } // T 泛型类型由传入的参数类型决定 public static <T> T fun(T t) { return t; } }
————————
泛型总结:
泛型特性解决的是向下转型所带来的安全隐患,其核心的组成就是在声明类或接口中不用设置具体的参数类型;
? 符号可以接收任意的泛型类型,但是只能够取出,不能够修改
~~~~