JDK5 之 泛型
一、什么是泛型?
由来:
早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。
JDK5之前使用Object传输,然后进行向下转型,这里可能在运行期强转失败抛ClassCastException
异常,导致程序异常终止。
好处:
引入泛型可以将运行期异常转移到编译异常,在编写代码时就可以检测出问题。
避免了向下转型,提高了代码的扩展性。
注意:
泛型类型必须是引用类型;
泛型只在编译期有效,在运行期就擦除了。
泛型机制:
是一种将数据类型明确工作,推迟到创建对象或调用方法时才去明确的一种机制。
二、泛型的使用
泛型格式:<A,B,...>
1. 泛型类:public class 类名<E> {}
即定义在类上:public class 类名<泛型类型1,…>
//在类申明后申明通用类型E,则可以在变量、方法返回值和方法参数使用
public class MyClass<E> {
//在变量处使用通用类型,且并需在类申明后申明通用类型
public E e;
//此处报错因为,变量通用类型必须在类申明后申明
// T t;
//在方法返回值处使用通用类型
public E getE() {
return e;
}
//在方法参数使用通用类型
public void setE(E e) {
this.e= e;
}
//方法返回值通用类型 和 方法参数通用类型 可以在方法前申明
// 这就是 泛型函数 使用方法
public <T> T getT(T t) {
return t;
}
}
public class Test {
public static void main(String[] args) {
MyClass<String> c= new MyClass();
c.setE("111");
System.out.println(c.getE());
System.out.println(c.getT(123));
}
}
2. 泛型函数:public<T> void 函数名(T t){xxx}
即定义在函数上:public <泛型类型> 返回类型 方法名(泛型类型 变量名)
public class MyClass {
public<T> void show(T t){
System.out.println(t);
}
}
public class Test {
public static void main(String[] args) {
MyClass c = new MyClass();
c.show("111");
c.show(111);
c.show(1.11);
}
}
3. 泛型接口:public interface 接口名<E> {}
即定义在接口上:public interface 接口名<泛型类型>
public interface MyInterface<E> {
public abstract void show(E e);
}
//子类在实现接口时,这个接口上有泛型,就可以明确接口上的泛型的具体类型
public class MyClass1 implements MyInterface<String> {
@Override
public void show(String s){
System.out.println(s);
}
}
//子类在实现接口时,没有明确接口上的泛型,那就要定义成泛型类
public class MyClass2<E> implements MyInterface<E> {
@Override
public void show(E e){
System.out.println(e);
}
}
public class Test {
public static void main(String[] args) {
MyClass1 c1=new MyClass1();
c1.show("111");//111
MyClass2<Integer> c2 = new MyClass();
c2.show(11);//11
}
}
三、泛型通配符(?)
- 通配符问号(?):表示任意类型,如果没有明确,那么就是Object以及任意的Java类。如
List<?>
表示可以存放任意对象类型的List,和List<Object>
一样。- 连接限制符:extends:向下限定,E及其子类
? extends E
- 连接限制符:super:向上限定,E及其父类
? super E
public class TestGeneric {
public static void main(String[] args) {
//泛型如果明确写的时候,前后必须一致,可以加Collections.singleton()转型
Collection<Object> o = new ArrayList<Object>();
Collection<?> o1 = new ArrayList<Object>();
Collection<?> a = new ArrayList<A>();
Collection<Object> a1 = Collections.singleton(new ArrayList<A>());
// Collection<Object> b = new ArrayList<B>();//报错
//? extends E 向下限定
Collection<? extends A> collection = new ArrayList<A>();
Collection<? extends A> collection1 = new ArrayList<C>();
Collection<? extends A> collection2 = new ArrayList<B>();
//? super E 向上限定
Collection<? super A> aaa = new ArrayList<Object>();
ArrayList<Integer> integers = new ArrayList<>();
integers.add(100);
// integers.addAll(integers2); //报错,因为做了向下限定:
// boolean addAll (Collection < ? extends Integer > c)
// 按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。
// boolean addAll (Collection < ? extends E > c)
ArrayList<Object> integers2 = new ArrayList<>();
integers2.add(200);
}
}
class A {}
class B extends A {}
class C extends A {}
若有不正之处,请谅解和批评指正,谢谢~
转载请标明:
https://blog.csdn.net/vihem/article/details/121083039