Java:泛型
泛型
泛型是JDK1.5中加入的新特性,用于解决数据类型的安全性问题。
- 通过在类声明时通过一个标识表示类中某个属性的类型或某个方法的返回值及参数类型。
- 保证代码运行时不产生 ClassCastException异常
- Java中的泛型只在编译阶段有效****,不进入运行阶段
泛型类
- 对象实例化时不指定泛型,默认为Object
- 泛型不同的引用不能相互赋值
/**
* 此处的泛型T可以任意取名为A,B,V
* 一般使用大写T,
* @param <T>
*/
class A<T>{
private T key;
//此处T为获取的形参的类型
public void setKey(T key){
this.key = key;
}
//此处T为返回值的类型
public T getKey(){
return this.key;
}
}
测试用例:
A<String> a1 = new A<String>();
a1.setKey("泛型类测试");
System.out.println(a1.getKey());
//在不进行泛型设置时,默认为Object
A a2 = new A();
a2.setKey(new Object());
Object a3 = a2.getKey();
泛型接口
- 定义接口时添加泛型
interface IB<T>{
T test(T t);
- 定义实现类
- 未传入泛型实参时,与泛型类的定义相同
- 声明类的时候,需在类中声明泛型的类型
class B1<T> implements IB<T>{
@Override
public T test(T t) {
return t;
}
}
- 如果实现接口时指定接口的泛型的具体数据类型
- 这个类实现接口所有方法中都要泛型替换实际的具体数据类型
class B2 implements IB<String>{
@Override
public String test(String s) {
return null;
}
}
- 使用案例
//B1可以指定泛型也可以默认为Object
B1<String> b1 = new B1();
//B2不能指定泛型的类型
B2 b2 = new B2();
泛型方法
-
无返回值方法的泛型
<T>
是对方法类的定义
public <T> void test(T s){
T t = s;
}
-
有返回值方法的泛型
<T>
是对方法类的定义,T
是返回值的类型
public <T> T test2(T s){
return s;
}
- 可变长方法的泛型
public <T> void Test3(T... s){
for(T s1 : s){
System.out.println(s1);
}
定义类的泛型
- 在类上定义的泛型的变量,可以在普通(非静态)方法中调用
class C<E>{
//在类上定义的泛型的变量,可以在普通方法中调用
private E e;
public <T> void test(T s){
System.out.println(this.e);
T t = s;
}
- 静态方法不可调用类中定义的泛型变量
- 泛型的变量不能静态化(可能因为类型不确定)
- 只能使用静态方法自己定义的泛型变量
class C<E>{
private E e;
public static void test4(){
//调用e报错
System.out.println(e);
}
- 泛型方法在调用前没有固定类型
- 在调用时,泛型为传入参数的类型,即确定泛型的类型
C<Object> c = new C<Object>();
c.test("9");
Integer i = c.test2(2);
c.test2(true);
通配符
- 在不清楚需要进行泛型的数据类型时,使用
<?>
进行限制
class D{
//test方法需要一个list集合的参数,但不清楚list集合的数据类型
public void test(List<?> list){
}
}
- 限制的通配符
<? extends Person>
:只允许泛型为Person及Person子类的引用调用<? super Person>
:只允许泛型为Person及Person的父类的引用调用<? extends Comparable>
:只允许泛型为实现Comparable接口的实现类的引用调用
类的定义:
- D -> C -> B - > A
- IAImpl 是接口 IA 的实现类
class A1{}
class B3 extends A1{}
class C1 extends B3{}
class D1 extends C1{}
interface IA{}
class IAImpl implements IA{}
测试方法类:
class D2{
public void test1(List<? extends C1> list){}
public void test2(List<? super C1> list){}
public void test3(List<? extends IA> list){}
}
<? extends C1>
:
List<C1> list1 = new ArrayList();
List<D1> list2 = new ArrayList();
List<B3> list3 = new ArrayList();
List<A1> list4 = new ArrayList();
d2.test1(list1);
d2.test1(list2);
//d2.test1(list3); 报错,B为C的父类
<? super C1>
:
d2.test2(list1);
//d2.test2(list2);报错,D为C的子类
d2.test2(list3);
d2.test2(list4);
<? extends IA>
List<IAImpl> list5 = new ArrayList();
d2.test3(list5);