21-泛型

泛型

泛型是从JDK1.5之后追加到Java中,主要是为了解决ClassCastException问题,在进行对象向下转型过程中永远存在安全隐患,而Java希望通过泛型慢慢解决此类问题。

泛型问题引出

假设定义描述x,y坐标处理类,允许保存三类数据:

  • 整形
  • 浮点型
  • 字符型

于是设计类是就需要具体考虑x,y属性的类型,保存以上三种类型数据,做法是利用Object类进行定义,则存在以下转型关系:

  • 整形:基本数据类型->包装为Integer对象->自动向上转型为Object
  • 浮点形:基本数据类型->包装为Double对象->自动向上转型为Object
  • 字符串形:String类对象->自动向上转型为Object;

Object可以接受所有数据类型,则会存在严重安全隐患;

泛型基本定义

为了避免“ClassCastException”最好的做法是可以直接回避掉对象的强制转换;
所以在JDK1.5之后,提供泛型技术,泛型本质在于类中的方法或方法的参数与返回值类型可以由对象实例化的时候动态决定。
此时需要在类定义时明确的定义占位符(泛型标记)

class Point <T>{
	private T x;
	private T y;
} 

此时类中的属性数据类型并不确定,而是由外部决定。
提示:关于默认的泛型类型:
由于泛型是属于JDK1.5之后的产物,但是在这之前已经有不少内置的程序类或接口广泛的应用在开发中,于是为了保证这些类或接口追加泛型后依然可以使用,所以如果不设置泛型类型时,自动将使用Object作为类型以保证程序的正常执行,但是在编译过程中会出现警告信息。
泛型使用注意点:

  • 泛型之中只允许设置引用类型,如果现在要操作基本类型必须使用包装类;
  • 从JDK1.7开始,泛型对象实例化可以简化为Point<Integer> point = new Point()

使用泛型可以解决大部分的类对象的强制转换处理,这样的程序才是一个合理的设计。

泛型通配符

虽然泛型帮助开发者解决了一系列的对象的强制转化带来的安全隐患,但泛型也带来了新的问题:引用传递处理。
但是如果不设置泛型,那么在方法之中就有可能对你的数据进行修改,所以此时需要一种方案:可以接收所有的泛型类型并且不能修改里面的数据(允许获取),那么就需要通过通配符“?”来解决;
public void fun(Message<?> temp)
在“?”基础上实际上还提供两类小的通配符:

  • "?extends"类:设置泛型上限
    • 如"?extends Number":表示该泛型只允许设置Number或Number子类;
  • "?super"类:设置泛型下限
    • 如"?super String":表示该泛型只允许使用String或其父类;

public void fun(Message<?extends Number> temp)
通配符是一个重要的概念,要求一定可以理解此概念的定义,日后学习Java类库是会见到大量通配符使用。

泛型接口

泛型除了可以在类上定义之外也可以在接口之中进行使用,例如,定义一个泛型接口,对于泛型接口的子类有两种实现方式

interface IMessage<T>{
	public String echo(T t);
	
}
//实现方式一
class MessageImpl<S> implements IMessage<S>{
	public String echo(S t){
		return "ECHO" + t;
	}
}
//实现方式二:在子类实现父接口的时候直接定义出具体泛型类型
class MessageImpl implements IMessage<String>{
	public String echo(S t){
		return "ECHO" + t;
	}
}

从概念和实现上来讲不复杂,但日后会遇见大量出现有泛型的接口,这个时候要清楚有两种实现原则。

泛型方法

之前的程序类里实际上可以发现在泛型类中如果将泛型标记写在了方法上,称为泛型方法。
需要注意,泛型方法不一定非要出现在泛型类之中,即如果一个类中没有定义泛型,也可以使用泛型方法。后期进行项目开发时,这种泛型方法很常见。
如果一个项目有过多接口,可使用泛型扩展接口。

猜你喜欢

转载自blog.csdn.net/MARVEL_3000/article/details/111400726