第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
}
}
}