Java-泛型的使用

1.泛型

1.1 泛型的基本概念

  • 实现了对功能代码的复用,封装,同时对数据类型进行统一的约束
  • 格式:<自定义泛型无意义大写字母占位符>

1.2 泛型的使用

1.2.1 泛型在方法上的使用(使用的是静态方法)
  1. 声明格式:
public static <T>  T(返回值类型)  方法名(一个对应泛型的参数) { 
	//方法体
}
  1. 自定义的泛型声明在返回值之前,保证返回值以及参数都可以使用自定义的泛型。
  2. 在方法上定义的泛型,需要通过调用方法时通过给定的参数来进行约束,所以在方法参数列表内必须要有一个参数是对应声明的自定义泛型。
    在这里插入图片描述
1.2.2 泛型在类中使用
  1. 声明格式;
class TypeA<T> {
}
  1. 类声明自定义泛型,需要通过实例化对象时指定的数据类型来进行约束。
TypeA<String> typeA = new TypeA<Stirng>();
  1. 在实例化对象时对类声明的自定义泛型进行约束之后,在类内所以使用该泛型占位符的地方都是使用的该数据类型。
  2. 在实例化对象时若没有明确告知编译器泛型对应的数据类型,那么会默认为Object类型,虽然支持传入任意类型参数,但是缺少了数据类型一致化的约束。
  3. 类内的静态方法不能使用类声明自定义的泛型,如下图,这样是不允许的,原因在最后讲解。
class TypeA<T> {
	public static void test1(T t) {
		//此处是一个静态方法
	}
}
  1. 类内的静态方法可以自定义属于自己的泛型,但是静态方法自定义泛型占位符不能与类声明自定义的泛型的占位符相同,避免不必要的歧义在被调用时,通过参数来进行约束。
class TypeA<T> {
	public static <E> void test2(E e) {
		//这里是一个定义了自己的自定义泛型的静态方法
	}
}

在这里插入图片描述

1.2.3 泛型在接口上的使用
  1. 声明格式:
interface 接口名<T> {
	//接口的成员
}
  1. 接口声明的自定义泛型有且只能用于成员方法,不可以用于接口中的成员变量上,如下代码是不允许的,原因在最后解释。
interface MyInterface<T> {
	//T Field = 无法初始化;
}
  1. 接口声明的泛型其遵从接口的实现类有两种方式使用泛型。
  • 自由模式 : 泛型的约束交由遵从接口的实现类实例化对象时,指明泛型对应的数据类型来对其约束。
interface MyInterface<T> {
	//接口的成员
}

class TypeA<T> implements MyInterface<T> {
	//类的成员
}

//由实例化对象时指定泛型所对应的数据类型来进行约束
TypeA<String> typeA = new TypeA<Stirng>();
  • 规矩模式 : 类遵从接口时,接口的泛型对应的具体数据类型就已经确定,实例化对象时不需要再对其进行约束。
interface MyInterface<T> {
	//接口的成员
}

class TypeA implements MyInterface<String> {
	//类的成员
}

//因为TypeA类遵从接口时,接口的泛型对应的具体数据类型就已经确定,
//所以实现类实例化对象时不需要再对其进行约束
TypeA typeA = new TypeA();

TypeB类在遵从接口时,接口对应的泛型的数据类型已经明确,此时TypeB可以自定义属于自己的泛型,接口的泛型对应的数据类型只会约束TypeB类中完成的接口当中未实现的方法,不会约束实现类自定义的成员,如下代码所示:

interface MyInterface<T> {
	//接口的成员
	void print(T t);
}

class TypeB<T> implements MyInterface<String> {
	//TypeB重写接口中缺省属性为public abstract的方法print
	public void print(String str) {
		System.out.println(str);
	}
	
	//属于TypeB本类的方法
	public T typeBMethod(T t) {
		return t;
	}
}

//TypeB类实例化对象,约束自己自定义的泛型
TypeB<Integer> typeB = new Type<Integer>();

但是如下代码是不允许的:

interface MyInterface<T> {
	//接口的成员
}

class TypeB<E> implements MyInterface<T> {
	//TypeB重写接口中缺省属性为public abstract的方法print
	public void print(T t) {
		System.out.println(str);
	}
	
	//属于TypeB本类的方法
	public E typeBMethodE e) {
		return t;
	}
}

//TypeB类实例化对象,约束自己自定义的泛型
TypeB<Integer> typeB = new Type<Integer>();

在接口的泛型所对应的数据类型没有明确的情况下,实现类自定义属于自己的泛型数据类型,那么当实现类实例化对象的时候,对泛型的约束是针对于实现类自定义的泛型,而遵从的接口的泛型所对应的自定义泛型将无法再确定,所以这是不允许的。

1.3 泛型使用需要注意到的问题

1.3.1 为什么类内的静态方法不能使用类自定义的泛型
  1. 静态方法是在类文件加载的时候就会准备好的,如果在静态方法上使用类自定义的泛型,那么在加载类文件时就无法明确具体的数据类型,导致无法加载。
  2. 类声明的自定义泛型需要通过实例化类对象时来进行约束,但是静态方法可以在没有对象的时候通过类名直接调用,如果静态方法上使用类声明的自定义泛型,那么在通过类名直接调用静态方法时无法明确对应的数据类型。
1.3.2 为什么接口的成员变量不能使用接口自定义的泛型修饰
  • 与final关键字有关,接口内的成员变量的缺省属性为 public static final,final关键字修饰的成员变量必须在声明时初始化,如果在成员变量上使用接口自定义泛型,那么在初始化时无法明确具体的数据类型,进而无法初始化。
发布了6 篇原创文章 · 获赞 5 · 访问量 338

猜你喜欢

转载自blog.csdn.net/cccccv_/article/details/104520528