啥是泛型
泛型,就是泛指的数据类型,当代码中的功能代码可以复用,但是数据类型设置单一,如果需要更换数据类型,就必须重新完成一个对应数据类型但是功能完全一样的代码,工作是重复的。假如有一个工厂生产商品,让该工厂生产某个型号的商品,不可能让该工厂而拆了重组才能生产对应的型号。Java中的泛型,就是来解决数据类型的对应问题。
格式
<自定义泛型无意义大写英文字母占位符>
比如:<T> :type <E>:element <K>:key <V>:value
泛型的使用
泛型可以在方法中使用
泛型可以在类中使用
泛型可以在接口中使用
1.泛型在类中使用
格式:
class 类名<自定义泛型无意义大写字母占位符>{
在类内的成员变量和成员方法都可以使用自定义泛型
建议:成员变量不建议使用自定义泛型
}
使用注意事项:
① 类声明自定义泛型,需要通过创建对象的方式来约束
TypeA<String> typeA = new TypeA<String>();
//Eclipse 标准写法 前后约束的泛型类型要一致,这里都是String
②类声明泛型约束后,在类内的所有成员方法中使用的泛型都是类约束的泛型具体数据类型
③如果没有约束类声明泛型,所有使用到泛型的位置都是Object【不推荐】
④类声明的自定义泛型不能用于类内的静态方法【因为没有对象】
/*
* 定义一个带有自定义泛型的类
*/
class TypeA<T> {
/**
* 使用和类名一致的自定义泛型,需要通过【类对象来约束】
* @param t 对应泛型具体数据类型的参数
* @return 对应泛型具体数据类型的返回值
*/
public T test1(T t) {
return t;
}
/**
* 使用和类名一致的自定义泛型,需要通过【类对象来约束】
* @param t1 对应泛型具体数据类型的参数
* @param t2 对应泛型具体数据类型的参数
*/
public void test2(T t1, T t2) {
System.out.println(t1);
System.out.println(t2);
}
}
public static void main(String[] args) {
//类内所有使用到泛型占位符的位置都是T类型
//明确告知编译器,这里泛型对应的具体数据类型都是String
TypeA<String> typeA = new TypeA<String>();
typeA.test1(t);
}
2.泛型在方法中使用
格式:public static <T> 返回值类型 [自定义泛型] 方法名(必须存在一个对应泛型的参数){
//方法体内可以使用自定义泛型
}
举个例子:
/**
* 带有自定义泛型声明的方法
* @param <T> 自定义泛型无意义占位符
* @param t 指定的泛型数据类型,由用户约束
* @return 对应的T类型,具体类型由用户约束
*/
public static <T> T test (T t) {
return t;
}
/*
*test方法使用了自定义泛型,传入的实际参数是什么类型
*泛型T对应的具体数据类型就是什么类型
* 免去了频繁更换数据类型而导致的重写代码的麻烦
*/
Integer test = test(123);
String test2 = test("你好");
Demo1 test3 = test(new Demo1());
/**
* 创建一个可以保存任意类型的数组
*/
public static <T> void printArray(T[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
/*
* string类型
*/
String arr[] = {"江坤","江坤坤","江江坤","江江坤坤"};
printArray(arr);
/*
* Integer类型
*/
Integer arr2[] = {1,2,3,4,5,6,8};
printArray(arr2);
/*
* Demo1类型
*/
Demo1 arr3[] = {new Demo1(),new Demo1(),new Demo1(),new Demo1(),new Demo1()};
printArray(arr3);
以上打印结果,皆可正确显示。
3.泛型在接口中使用
格式:
interface 接口名<自定义泛型无意义占位符>{
接口的泛型不能用于成员变量中,因为当前的泛型数据类型是不明确的,无法进行初始化过程
接口中的泛型有且只能用于成员方法
}
注意事项:
①接口声明的泛型,有且只能用于类内的成员方法
②遵从带有自定义泛型的接口的类,一种可以遵从过程中明确告知泛型的具体类型,一种是在创建类对象时明确泛型具体数据类型
③class TypeA<T> implements A<String> 正确
接口的泛型明确接口中的方法,使用泛型对应的具体数据类型,类声明的泛型用于自定义约束自己类内的方法
④class TypeA<E> implements A<T> 错误
接口中的泛型没有明确数据类型,也无法通过类创建对象的过程中明确泛型对应的具体数据类型,无法编译
interface A<T>{
void test(T t);
}
/*
* 接口带有泛型,遵从接口的实现类有两种方案可以implemets当前接口
* 1.自由
* 2.规矩
*/
自由方式:
/**
* 自由方式,类名之后的自定义泛型和接口的自定义泛型同名,泛型对应的具体数据类型时需要在创建
* 当前类对象时进行约束使用
* @author kk
*
* @param <T> 遵从接口和接口一致的泛型
*/
class TypeB<T> implements A<T>{
@Override
public void test(T t) {
// TODO Auto-generated method stub
}
}
规矩方式:
/**
* 规矩模式:遵从接口时,接口使用泛型对应的具体数据类型已经明确,为<String>
* 在类内使用接口中缺省属性为public abstract方法时,泛型已确认
* 为(String t)
* @author kk
*
*/
class TypeC implements A<String>{
@Override
public void test(String t) {
}
|
|