Java泛型
泛型主要目的是为了解决ClassCastException的问题
举个栗子
package com.test;
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 this.x ;
}
public Object getY() {
return this.y ;
}
}
public class JavaDemo { // 主类
public static void main(String args[]) { // 主方法
Point point = new Point() ;
point.setX(10) ; // 自动装箱&向上转型
point.setY(20) ; // 自动装箱&向上转型
int x = (Integer) point.getX() ; // 向下转型 & 自动拆箱
int y = (Integer) point.getY() ; // 向下转型 & 自动拆箱
System.out.println("x = " + x + "、y = " + y) ;
}
}
运行结果:
此时,Object可以接受所有的数据类型,但是正因如此,程序会出现安全隐患
具有安全隐患的代码
package com.test;
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 this.x ;
}
public Object getY() {
return this.y ;
}
}
public class JavaDemo { // 主类
public static void main(String args[]) { // 主方法
Point point = new Point() ;
point.setX(10) ; // 自动装箱&向上转型
point.setY("北纬20度") ; // 向上转型
int x = (Integer) point.getX() ; // 向下转型 & 自动拆箱
int y = (Integer) point.getY() ; // 向下转型 & 自动拆箱
System.out.println("x = " + x + "、y = " + y) ;
}
}
运行结果:
此时,程序在执行"int y = (Integer) point.getY()"语句,出现安全隐患
但是,程序编译是完全可以通过的,但是执行后会出现 “ClassCastException” 异常
使用泛型,从而避免"ClassCastException"
package com.test;
class Point<T> { // T表示Type
private T x ;
private T 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 ;
}
}
public class JavaDemo { // 主类
public static void main(String args[]) { // 主方法
Point<Integer> pointA = new Point<Integer>() ;
Point<String> pointB = new Point<String>() ;
pointA.setX(10) ;
pointA.setY(20) ;
System.out.println("x = " + pointA.getX() + "、y = " + pointA.getY()) ;
pointB.setX("东30");
pointB.setY("西30");
System.out.println("x = " + pointB.getX() + "、y = " + pointB.getY()) ;
}
}
运行结果:
此时,程序设置了泛型"T",
在main方法中实例化对象pointA (“Point pointA = new Point()”)的时候进行了Integer类型的定义
实例化对象pointB (“Point pointB = new Point()”)的时候进行了String类型的定义
注意
- 泛型中只允许设置引用类型,如果要操作基本类型,必须使用包装类;
- 从JDK1.7开始,泛型对象实例化可以简化为"Point pointB = new Point<>() ;"
引用传递
package com.test;
class Message<T> {
private T info ;
public void setInfo(T info) {
this.info = info ;
}
public T getInfo() {
return this.info ;
}
}
public class JavaDemo { // 主类
public static void main(String args[]) { // 主方法
Message<String> msg = new Message<String>() ;
msg.setInfo("今天好热") ;
fun(msg) ;
}
public static void fun(Message<String> temp) {
System.out.println(temp.getInfo()) ;
}
}
运行结果:
"Message"对象"msg"定义了"String"类型, 方法"fun()"只能接收"Message< String>"类型;
此时,出现一个问题,如果程序使用了泛型,那么就不可能只是一种类型,则fun()方法应该可以接收任意类型
使用通配符"?"来解决问题
package com.test;
class Message<T> {
private T info ;
public void setInfo(T info) {
this.info = info ;
}
public T getInfo() {
return this.info ;
}
}
public class JavaDemo { // 主类
public static void main(String args[]) { // 主方法
Message<String> msg = new Message<String>() ;
msg.setInfo("今天好热") ;
fun(msg) ;
Message<Integer> ms = new Message<Integer>() ;
ms.setInfo(10) ;
fun(ms) ;
}
public static void fun(Message<?> temp) {
System.out.println(temp.getInfo()) ;
}
}
运行结果:
在通配符"?"的基础上,还提供两类小的通配符:
- ? extends 类:设置泛型的上限
例如:"? extends Number":表示该泛型类型只允许设置"Number"或者"Number"的子类- ? super 类:设置泛型的下限
例如:"? super String":表示该泛型类型只允许使用"String"或"String"的父类
泛型接口
interface IMessage<T> {
public String test(T t) ;
}
对于泛型接口的子类而言有两种实现方式:
- 在子类之中继续设置泛型定义
package com.test;
interface IMessage<T> {
public String test(T t) ;
}
class MessageImpl<S> implements IMessage<S> {
public String test(S t) {
return "【测试】" + t;
}
}
public class JavaDemo { // 主类
public static void main(String args[]) {
IMessage<String> msg = new MessageImpl<String>() ;
System.out.println(msg.test("测试"));
}
}
运行结果:
- 在子类实现父接口的时候直接定义出具体泛型类型
package com.test;
interface IMessage<T> {
public String test(T t) ;
}
class MessageImpl implements IMessage<String> {
public String test(String t) {
return "【测试】" + t;
}
}
public class JavaDemo { // 主类
public static void main(String args[]) {
IMessage<String> msg = new MessageImpl() ;
System.out.println(msg.test("测试"));
}
}
运行结果:
泛型方法
如果将泛型标记写在了方法上,那么这样的方法就被称为泛型方法
如果一个类上没有定义泛型,那么也可以使用泛型方法,举个栗子:
package com.test;
public class JavaDemo { // 主类
public static void main(String args[]) { // 主方法
Double [] result = init(1.1,2.2,3.3) ; // 由外部设置泛型类型
for (double temp : result) {
System.out.print(temp + "、") ;
}
}
public static <T> T[] init(T ... args) {
return args ;
}
}
运行结果: