第22 章 : 泛型
96 泛型问题引出
JDK >= 1.5
主要为了解决 ClassCastException
举例:
要描述一个坐标类,允许存放以下坐标数据类型
整型 x = 10, y = 20
浮点型 x = 10.1, y = 20.2
字符串型 x = 东经 10 度 , y = 北纬 20 度
可以使用Object,不过会出现转型操作
整型: 基本数据类型 -> Integer包装类 -> 自动向上转型为Object
浮点型 :基本数据类型 -> Double包装类 -> 自动向上转转型为Object
字符串型 :String对象 -> 自动向上转转型为Object
class Point{ private Object x ; private Object y ; public Point(Object x, Object y){ this.x = x ; this.y = y ; } public void setX(Object x){ this.x = x ; } public void setY(Object y){ this.y = y ; } public Object getX(){ return this.x ; } public Object getY(){ return this.y ; } @Override public String toString(){ return "Point("+ this.x + ", " + this.y + ")" ; } } class Demo{ public static void main(String[] args) { Point p1 = new Point(1, 2); System.out.println(p1); // Point(1, 2) int x = (Integer)p1.getX() ; System.out.println(x); // 1 Point p2 = new Point(1.1, 2.2); System.out.println(p2); // Point(1.1, 2.2) // Object 不能约束传入的参数 Point p3 = new Point(10, "北纬20度"); System.out.println(p3); // Point(10, 北纬20度) } }
97 泛型基本定义
类中属性或方法的参数与返回值类型由对象实例化的时候动态决定
需要在类定义的时候明确的定义占位符(泛型标记)
实例化不设置泛型类型,默认使用Object
Point<Integer> p1 = new Point<Integer>(1, 2);
泛型的好处:
1、编译时检查类型,避免出现安全隐患
2、避免向下转型操作
泛型注意点:
1、只能使用引用类型,基本类型要使用包装类
2、JDK >=1.7开始可以简写
Point<Integer> p1 = new Point<>(1, 2);
使用泛型可以解决大部分的类对象强制转换处理
class Point<T>{ private T x ; private T y ; public Point(){} public Point(T x, T y){ this.x = x ; this.y = y ; } public void setX(T x){ this.x = x ; } public void setY(T y){ this.y = y ; } public T getX(){ return this.x ; } public T getY(){ return this.y ; } @Override public String toString(){ return "Point("+ this.x + ", " + this.y + ")" ; } } class Demo{ public static void main(String[] args) { Point<Integer> p1 = new Point<Integer>(1, 2); System.out.println(p1); // Point(1, 2) int x = (Integer)p1.getX() ; System.out.println(x); // 1 Point<Double> p2 = new Point<Double>(1.1, 2.2); System.out.println(p2); // Point(1.1, 2.2) Point<String> p3 = new Point<String>("东经30度", "北纬20度"); System.out.println(p3); // Point(10, 北纬20度) } }
98 泛型通配符
目前的泛型进行引用传递
class Message<T>{ private T content; public void setContent(T message){ this.content = message; } public T getContent(){ return this.content; } } class Demo{ public static void main(String[] args) { Message<String> message = new Message<>(); message.setContent("Hello Java"); showMessage(message); } // 只能接收Message<String> 对象 public static void showMessage(Message<String> message){ System.out.println(message.getContent()); // Hello Java } }
修改为通配符接收数据
public static void showMessage(Message<?> message) { System.out.println(message.getContent()); // Hello Java }
设置泛型范围
// 设置泛型上限 // ? extends 类 // 例如:只允许设置Number 或其子类 ? extends Number // 设置泛型下限 // ? super 类 // 例如:只能够使用String 或其父类 ? super String
public static void showMessage(Message<? extends Number> message) { System.out.println(message.getContent()); } public static void showMessage(Message<? super String> message) { System.out.println(message.getContent()); }
99 泛型接口
1、实现类继续使用泛型
interface IMessage<T>{ public void echo(T t); } class Messageimpl<S> implements IMessage<S> { public void echo(S t){ System.out.println(t); } } class Demo{ public static void main(String[] args) { Messageimpl<String> message = new Messageimpl<>(); message.echo("Hello"); // Hello } }
2、实现类不使用泛型
interface IMessage<T>{ public void echo(T t); } class Messageimpl implements IMessage<String> { public void echo(String t){ System.out.println(t); } } class Demo{ public static void main(String[] args) { Messageimpl message = new Messageimpl(); message.echo("Hello"); // Hello } }
100 泛型方法
泛型方法:泛型标记写到了方法上
泛型方法不一定非要出现在泛型类中
class Demo{ public static <T> T[] getArray(T ...args){ return args; } public static void main(String[] args) { Integer[] list = getArray(1, 2, 3); for(int x : list){ System.out.println(x); // 1 2 3 } } }