Java泛型总结

一、概念解释

泛型类:

  • 引出:JDK1.5,为了解决程序中向下转型出现的参数转换安全问题
  • 解释:类在定义的时候不会设置属性或方法参数的具体类型,而是使用时定义
  • 基本语法:MyClass类就是一个泛型类
    class MyClass<T>{
        T value;//T代表变量类型,可以是任意类型,与<T>不同
    }

    <T>:T代表类型参数,可以指代任何引用类型这里指的是Object类可以接收的类型)

  • 常见参数类型:T(类)、E(元素)、K,V(键值对)

  • 作用:

  1. 用于检测编译期,参数类型设置问题,只有传入参数与使用定义类型一致时才可设置

  2. 杜绝向下转型带来的隐患

二、泛型方法

  • 语法
public <T> T test(T t){
    return t;
}
  1. 第一个T:<T>,代表类型参数,不能省略,要写在第二个T之前
  2. 第二个T:代表方法的返回值类型
  3. 第三个T:代表方法参数的类型
  • 与泛型类共存
  1. 若泛型类与泛型方法共存,使用同一个类型参数,泛型类T与泛型方法T没有任何联系,泛型方法始终以自己定义的类型参数为准
  2. 建议使用不同的标识
  3. 应用:
package generics;

//泛型
class Point<T>{
	private T x;
	private T y;
	
	public T getX() {
		return x;
	}
	public void setX(T x) {
		this.x = x;
	}
	public T getY() {
		return y;
	}
	public void setY(T y) {
		this.y = y;
	}
	
	@Override
	public String toString() {
		return "Point [x=" + x + ", y=" + y + "]";
	}
}

public class Test {

	public static void main(String[] args) {
		Point<String> point = new Point<String>();
		point.setX("qwe");
		point.setY("asd");
		System.out.println(point);
		
		Point<Integer> point2 = new Point<>();//1.7后new后可以不写类型
		point2.setX(12);
		point2.setY(23);
		System.out.println(point2);
	}
}

运行结果

 

三、通配符

  • 引出:解决参数统一问题,可以接收所有的泛型类型,又不能让用户(main)直接修改,使用通配符
  • ?用于方法参数,指代任意类型
  1. eg:fun(MyClass<?> myclass) //表示可以接收任意类型的MyClass对象
  2. 由于类型无法确定,所以只能取得值,不能修改
  • ?extend 类 :设置泛型上限,可用于类或方法参数
  1. eg:?extend Number:表示只能接收Number或其子类
  2. 用于方法参数时,只能取得值不能修改(类型无法确定)
  • ?super 类 :设置泛型下限,只能用于方法参数
  1. ?super String :表示只能接收String或其父类(Object)
  2. 可以修改值,类型已确定,自己或父类,若此时?为父类,会默认发生向上转型
  3. 应用:
package generics;

//通配符
class MyClass<T>{
	private T value;
	
	public MyClass(T value) {
		super();
		this.value = value;
	}

	public T getValue() {
		return value;
	}

	public void setValue(T value) {
		this.value = value;
	}
}

public class Test1 {

	public static void main(String[] args) {
//		fun(new MyClass <Integer>(10));
		
		fun(new MyClass <String>("qwe"));
		MyClass<String> myClass = new MyClass<>("123");
		MyClass<String> myClass1 = new MyClass<String>("123");
		fun(myClass);
		
//		fun(new MyClass <Double>(10.2));
		
		fun(new MyClass<Object>("123"));
		
		MyClass <Object> object = new MyClass<>("123");
		fun(object);
	}
	
//	//所有类型
//	public static void fun(MyClass<?> myClass) {
//		System.out.println(myClass.getValue());//适用于所有类型
//	}
	
//	//Number或其子类
//	public static void fun(MyClass<? extends Number> myClass) {
//		System.out.println(myClass.getValue());//运行结果:10 10.2
//	}
	
	//String或其父类Object
	public static void fun(MyClass<? super String> myClass) {
		myClass.setValue("hello");
		System.out.println(myClass.getValue());//运行结果:hello
	}
}

四、泛型接口

  • 定义:接口定义上使用此占位符<T>表示泛型接口
  • 子类实现接口:
  1. 继续保留泛型:class MyClassImpl implements MyClass<T>
  2. 声明泛型类型:class MyClassImpl implements MyClass<String>

五、泛型擦除

  • 解释:泛型是JDK1.5才引入的,而泛型能与之前的代码很好的兼容,这是因为泛型信息只存在于代码编译阶段,进入JVM之前,与泛型相关的信息会被擦除掉,这就是泛型擦除
  • 所以,在JVM中泛型类与普通类没有任何区别
  • 泛型、自动拆装箱、foreach都是Java中的语法糖(方便开发者使用,只存在于编译阶段,在运行阶段无用)
  • 在泛型类被擦除时,之前泛型类中的参数如果没有指定上限,<T>会被转译为Object,若指定上限,<T>会被转译为类型上限
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值