1.为什么要使用泛型
在实际开发中,对于数据类型一致化的要求是非常重要的!!!
例如:
ArrayList list = new ArrayList();
如果这里没有对可以保存到ArrayList中的数据类型进行约束,这里会导致一些因为数据类型一致化导致的问题:
1. 代码中会出现没有必要的强制类型转换,浪费时间浪费效率
2. 后期操作ArrayList发现数据类型不一致,导致其他操作问题
使用泛型约束之后:
ArrayList < String> list = new ArrayList();
< String>就是泛型约束,要求当前ArrayList中能够保存的数据是String类型。
1. 数据类型一致化!!!
2. 避免了没有必要的强制类型转换
3. 错误前置,要求保存的数据一致化,避免了因数据类型不一致导致的问题
4. 操作统一化
2.最基本的泛型格式
泛型:
<无意义占位符英文大写字母>
使用泛型用于约束数据类型,同时能够让代码更加普适性!!!
格式:
ArrayList< String> list = new Arraylist(); IDEA
ArrayList< String> list = new Arraylist< String>(); Eclipse
这里是告知Java编译器,当前ArrayList中,有且只能保存 String类型
错误格式
ArrayList< Object> list = new ArrayList< String>();
必须要求前后约束一模一样!!!
3. 自定义泛型在方法中使用
一个方法使用了自定义泛型,会让该方法变的非常的自由!!!
权限修饰符 [static] <自定义泛型无意义占位符> 返回值类型[可以使用自定义泛型] 方法名(必须有一个带有自定义泛型的参数) {
// 方法体
}
带有自定义泛型的方法,是依赖于方法的参数来确定泛型的具体数据类型!!!
在带有自定义泛型的方法,如果是独立存在的,一定要带有一个参数是自定义泛型!!!
public class Demo2 {
public static void main(String[] args) {
/*
public static <Demo2> Demo2 test(Demo2 t)
*/
Demo2 test = test(new Demo2());
/*
public static <String> String test(String t)
*/
String test1 = test("123213");
/*
public static <Integer> Integer test(Integer t)
*/
Integer test2 = test(1);
}
/**
*
* 带有自定义泛型的方法
*
* @param t 该参数用于【约束】泛型的具体类型
* @param <T> 自定义泛型占位符!!!
* @return 根据泛型的具体数据类型来确定!!!
*/
public static <T> T test(T t) {
System.out.println(t);
return t;
}
}
4. 自定义泛型在类中的使用
格式
class 类名<自定义泛型无意义占位符> {
// 类内的非静态成员变量和非静态成员方法可以使用类名声明的自定义泛型
}
为什么类内的静态成员方法不能使用和类名一致的自定义泛型???
静态成员方法是在类文件加载阶段就已经在内存的数据区加载完毕!!!
泛型的具体数据类型是在创建当前类对象时确定的!!!
静态成员变量泛型对应的具体数据类型还没有确定,就已经被加载,无法运行!!!
/**
* 带有自定义泛型的类
* @param <T> 自定义泛型占位符
*/
class Test1<T> {
/**
* 该方法使用了在类名上声明的自定义泛型
* @param t 和类名一致的自定义泛型
* @return 和类名一致的自定义泛型
*/
public T getType(T t) {
return t;
}
}
public class Demo3 {
public static void main(String[] args) {
Test1<String> stringTest1 = new Test1<>();
String type = stringTest1.getType("123");
}
}
自定义泛型在类中使用的总结:
1. 在类名之后使用自定义泛型占位符,声明当前类中带有泛型
2. 类名声明的自定义泛型,是在创建当前类对象时确定泛型对应的具体数据类型是哪一个
Test1< String> test1 = new Test1<>();
在类中所有使用到和类名一致的泛型位置,都会被替换!!!
3. 一个类带有自定义泛型,但是在创建当前类对象时没有约束泛型的具体数据类型,在类内
所有使用到和类名一致的自定义泛型, 都会被Object替换!!!【不建议】
4. 类名声明的自定义泛型不能用于静态成员方法
5. 自定义泛型在接口中的使用
格式
interface 接口名 {
// 有且只有成员方法可以使用自定义泛型
/*
接口中的成员变量缺省属性是public static final修饰
final修饰的成员变量定义时必须初始化,但是T类型是泛型,无法确定数据类型,无法初始化
*/
}
interface A<T> {
public void test(T t);
}
/*
类遵从接口 implements
1. 自由
2. 规矩
*/
/**
* 当前类带有泛型,而且泛型是和接口一致的!!!
* @param <T> 和接口一致的泛型
*/
class TestA<T> implements A<T> {
@Override
public void test(T t) {
}
}
/**
* 当前类遵从一个接口,接口带有泛型,而且当前接口确定了泛型对应具体数据类型
* 同时也就约束了,当前在接口中使用到泛型的方法对应的具体数据类型
*/
class TestB implements A<String> {
@Override
public void test(String s) {
}
}
public class Demo4 {
public static void main(String[] args) {
TestA<String> stringTestA = new TestA<>();
stringTestA.test("123");
TestA<Integer> integerTestA = new TestA<>();
integerTestA.test(10);
TestB testB = new TestB();
testB.test("123");
TestB testB1 = new TestB();
testB1.test("3321321");
}
}