java-泛型和通配符详解

为什么引入泛型

在我们代码编写中我们一个类常理来说一个属性只能接受一种类型。而我们如果需要多个类型转换就需要多个属性。而对应这个属性又有多个方法对之对应。这样就是的代码的复用性差。为了节省代码量,提供泛型。

泛型的定义

泛型有两种形式。泛型类和泛型方法。

泛型类的类型擦除

所谓的泛型类其实只是语法糖,也就是说泛型类仅存在用源码阶段,当代码进行编译后泛型就会被类型擦除,当进入JVM虚拟机后,和泛型有关的所有信息都会被擦除(类型擦除)如果泛型并没有使用通配符设置类型上限,泛型会被擦除为Object。如果指定了上限则会转为上限类型。
** 泛型类**
所谓的泛型类是指在类定义的时候不会设定类中属性或者方法参数的具体类型,而是在类使用时才定义类型。

class MyClass< T >{
	private T a;
	public T geta(){
		return a;
		}
	public void seta( T a){
		this.a = a;
	} 
}
main:
MyClass<String> myClass = new MyClass<>("aaa");
MyClass<Integer> myClass1 = new MyClass<Integer>(1);

在代码中T则时我们的泛型成为类型参数,用于指代任何类型,有几个典型的代表。
T表示一般类。
E表示Element,常用于泛型类中属性。
K/V表示键值对
S表示sebbyte子类

** 注意:**
泛型中的类型参数比如T只能接受类,所以基本数据类型必须使用包装类接收。
** 泛型方法**
语法:

class MyClass{
	public <T> void func(T t){
	System.out.println(t);
	}
} 

注意:
当泛型方法和泛型类共存的时候,当泛型类的类型参数和泛型方法的类型方法同名时,泛型方法始终以自己定义的类型参数为准。

泛型的意义

泛型很像是我们最后一道检查者,最后把关的人,泛型在编译期间会对对应的类进行语法检查类型是否统一,避免两个没有关系的对象进行强转时发生类型转换异常(运行时异常)

通配符?专用于方法中

使用语法:
public void print(MyClass<?> myclass){}
“ ? ”表示通配符用于方法参数时表示可以接收任意类型的泛型类MyClass。
但是用?接收的类对象,是不能够确定类中的属性类型的。所以,我们不能够对其内容进行修改,只能读取。

通配符 ? extends 类名

用于类上时使用语法:
class MyClass<T extends Number>{}
" T extends 类名 "表示使用时定义的接收的类型必须是该类名的子类。否则会异常报错。
用于方法上使用语法:
public void print(MyClass<? extends Number> myclass){}
在方法中:
" ? entends 类名"表示只能接收该类名的类或者其子类的泛型的泛型类参数。通过extends修饰的泛型类参数相当于确定了接收上限,都可以通过向上转型接收属性值。

通配符?super 类名

用于类上时语法:
class MyClass<T super String>{}
" T super 类名 "表示使用时定义的接收的类型必须是该类名对应的类或者其的父类。否则会异常报错。
用于方法上使用语法:
public void print(MyClass<? super String> myclass){}
在方法中:
" ? super 类型”表示该方法参数必须是泛型为该类名对应的类或者其父类的泛型类。通过super相当于确定了我们的泛型的下限。比如<? super String>则我们可以传Object和String两种类型的类。所以我们可以通过向下转型强转来设置该属性的值,比如:我参数串的Object给它设置String的时候系统会自动发生向上转型。所以super可以设置值也可以修改值。

泛型接口

语法:

interface IInterface<T>{
	T test(T t);
	}
//子类实现时可以选择继续保留泛型或者确定泛型对应类型
class InterfaceImpl<T>implements IInterface<T>{
	public T test(T t){}
}
class InterfaceImpl2 implements IInterface<String>{
	public String test(String str){}
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页