1.泛型技术
平时写代码,代码的类型如果不能确定,那会怎么办呢?
先看个错误的例子:
class Point {
private Object x ;
private Object y ;
//set、get构造方法略
}
public class Nice {
public static void main(String args[]) {
//设置数据
Point p = new Point() ;
p.setX("字符串");
p.setY(20);//运行之后才会报错
//取出数据
String x = (String) p.getX();
String y = (String) p.getY();
System.out.println( x + y );
}
}
设置的时候存放的是int,那么取出时是String,两个没有任何关系的对象之间要发生强制转换,就会产生ClassCastException
重点!向上转型的核心目的在于统一操作的参数上,而向下转型的目的是操作子类定义的特殊功能
JDK1.5之后加入了泛型技术,其核心意义在于:类的定义的时候,可以使用一个标记,此标记可以表示类中属性或方法参数的类型标记,在使用的时候才动态的设置类型
泛型例:
class Point <T> {
private T x ;
private T y ;
public void setX(T x){ //定义Type = T ,是一个类型
this.x = x ; //属性的类型不知道,由Point使用时动态决定
}
public void setY(T y){
this.y = y ;
}
public T getX() {
return x;
}
public T getY() {
return y;
}
}
public class Nice {
public static void main(String args[]) {
Point<String> p = new Point<String>() ;
p.setX("中文");
p.setY(10);//运行前报错
//由于接受的类型就是String,所以不需要向下强制转型了,下面括号中可省略
String x = p.getX();
String y = p.getY();
System.out.println(x + y);
}
}
使用泛型可以避免向下转型的问题,从而解决类转换的安全隐患
泛型能够采用的类型只能是类,即,不可以是基本类型,只能是引用类型
如:Point < Integer > p = new Point< Integer > ( );
注意:1.如果没有设置具体的泛型类型,会有警告,且使用Object表示
2. JDK1.7之后实例化泛型可以省略,Point p = new Point< > ( );
2.通配符
内部类,先看看:
//假设下面所用到的类与方法都已成功添加
public class Nice {
public static void main(String args[]) {
Message<Integer> m = new Message<Integer>();
m.setMsg(100);
fun(m);//引用传递
}
public static void fun(Message temp) {
temp.setMsg("hello") //输出hello
System.out.println(temp.getMsg());
}
}
//这种方法可以执行,但是它是带有警告的
//这个方法可以接受一个类的任意泛型,但是不可以修改,只能够取出,那么可以使用“?”来描述,只需将参数那里修改
public static void fun(Message<?> temp){...}
那么“?”通配符基础上还会有两个子的通配符:
1. ? extends 类:设置泛型上限,可以在声明上和方法参数上
如:? extends Number:意味着可以设置Number或者Number的子类(Integer,Double …)
2. ? super 类:设置泛型下限,可以声明在方法参数上
如:? super String : 意味着只能够设置String或者它的父类
下面看下两者的完整例子:
//设置泛型的上限
class Message <T extends Number> {
private T msg ;
public void setMsg(T msg) {
this.msg = msg ;
}
public T getMsg() {
return msg ;
}
}
public class Nice {
public static void main(String args[]) {
Message<Integer> m = new Message<Integer>();
m.setMsg(100) ;
fun(m);
}
public static void fun(Message< ? extends Number> temp) {
System.out.println(temp.getMsg());
}
}
//当然了,非Number或者非Number的子类的话,那么就语法错误了
//设置泛型的下限
class Message <T> { //下限就不是在这里加了
private T msg ;
public void setMsg(T msg) {
this.msg = msg ;
}
public T getMsg() {
return msg ;
}
}
public class Nice {
public static void main(String args[]) {
Message<String> m = new Message<String>();
m.setMsg(100) ;
fun(m);
}
public static void fun(Message< ? super String> temp) {
System.out.println(temp.getMsg());
}
}
3.泛型接口
泛型类型不仅仅定义在一个类里,泛型也可以在接口上声明,称之为泛型接口
有两种形式:
// 1.子类继续设置泛型
interface IMessage<T> { //设置多个泛型接口,用逗号隔开
public void print(T t) ;
}
class MessageImpl<T> implements IMessage<T> {
//子类也继续使用泛型,并且父类接口使用和子类的同样的泛型标记
public void print(T t) {
System.out.println(t);
}
}
public class Nice {
public static void main(String args [] ) {
IMessage<String> msg = new MessageImpl<String>() ;
msg.print("hello");
}
}
//2.在子类不设置泛型,而为父接口明确定义一个泛型类型
interface IMessage<T> { //设置多个泛型接口,用逗号隔开
public void print(T t) ;
}
class MessageImpl implements IMessage<String> {
public void print(String t) {
System.out.println(t);
}
}
public class Nice {
public static void main(String args [] ) {
IMessage<String> msg = new MessageImpl() ;//String可省
msg.print("hello");
}
}
4.泛型方法
泛型方法不一定非要在定义在支持泛型的类里
泛型方法例:
public class Nice {
public static void main(String args[] ) {
String str = fun("hello");
System.out.println(str.length());
}
//T的类型由传入的参数类型决定
public static <T> T fun(T t) {
return t ;
}
}
5.总结
1.泛型解决的向下转型所带来的安全隐患,其核心的组成就是在声明类或接口的时候不设置参数或属性的类型
2.”?”可以接收任意的泛型类型,只能够取出,但是不能够修改