第15章_泛型:


0:优秀博客:https://www.cnblogs.com/fengmingyue/p/6087031.html
1:泛型的目的之一:用来指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性。
2:泛型案例:
例1:“泛型类
public class Holder<T>{
        private T t;
        public Holder(T t){this.t = t;}
        public T getHolder(){return this.t;}
}
3:使用泛型告诉编译器你想使用什么类型,然后由编译器处理细节,在类上定义的泛型,不能在今天方法中使用
4:“元组”:将一组对象存储在一个对象中。通常元组具有任意长度,可以存储任意类型。(也叫做信使)
5:一段有意思的代码:
    Class c1 = New ArrayList<String>().getClass();
    Class c2 = New ArrayList<Integer>().getClass();
    System.out.println(c1 == c2);   //true     
 **这里需要注意:在泛型代码内部,无法获取任何有关泛型类型参数的信息。
6:java泛型是使用擦除来实现的。当你使用泛型时,任何具体的类型都被擦除了。
你唯一知道的是:你规范了一个类型。因此上面的ArrayList<String>和ArrayList<Integer>都被擦除成为了ArrayList类型。
   泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。

7:“边界”:类似<T extends HasF>这种重用了extends的泛型。它表示规范的类型是继承自HasF。
8:泛型在擦除时,将擦除到第一个边界(可能有多个边界),<T extends HasF>会擦除到HasF,这就像在类的声明中使用HasF代替了T一样。
9:泛型在java1.0中是没有的,由于之后要添加进去,所以使用了擦除这种折中的解决方案。
10:“泛型方法”:
例1:
    private static<T> void exchange(T[] arr, int i, int j) {
            T temp=arr[i];
            arr[i]=arr[j];
            arr[j]=temp;
    }
例2:
    public <T> T get(T[] ts) {
            return ts[ts.length / 2];
    }
11:通配符“?”
    public static void fun(List<Object> list) {…}
    List<String> list1 = new ArrayList<String>();
    List<Integer> list2 = new ArrayList<Integer>();
    fun(list1);//编译不通过
    fun(list2);//编译不通过
    //上面的调用都是编译不通过的!这说明想写一个即可以打印list1,又可以打印list2的方法是不可能的!
public static void fun(List<?> list) {…} //如果这里不使用泛型会警告,使用通配符即可。
但是使用通配符后,不能确定要类型,相关方法不能使用,例如:list.add("字符串");编译不通过。

  通配符有 3 种形式。

    1、<?> 被称作无限定的通配符

    2、<? extends T> 被称作有上限的通配符

    3、<? super T> 被称作有下限的通配符

12:基本类型不能写在泛型中(例如:ArrayList<int>)。
13:一个类不能同时实现一个泛型的两个变体。
例如:
    Interface A<T>{}
    Class B implements A<B>{}
    Class C extends B implements A<C>{}
    //由于擦除的原因,会将A<B>和A<C>都变为A。这样意味着C实现了两次A接口,编译不通过。
//但是将A接口的两个实现的泛型都去掉后,编译通过。(在使用java的一些基本接口时会遇到:Comparable<T>)
14:泛型方法重载
一下代码不能编译通过:
public Class A(){
            void f(List<W> w);
            void f(List<V> v)
}
        //由于擦除的原因,上面的两个方法产生的签名是一样的
¥¥此时正好听到了这首歌的这句话,颇有感慨。《明天会更好》:青春不解红尘。
15:“混型”:最基本的概念是:混合多个类的能力。
16、参数类型化:
//类型参数化
public class Cache<T> {
    T value;

    public Object getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

}

 代码:

泛型类:
class ClassGenericity<T> {
    //在类里面可以直接使用T的类型
    T aa;
    public void test11(T bb) {
        //................
    }
    //静态方法 在类上面定义的泛型,不能再静态方法里面使用
    public static <A> void test12(A cc) {
        //..................
    }

泛型使用在参数和返回值中。
public class MethodGenericity {
    //泛型使用在参数中
    private static<T> void exchange(T[] arr, int i, int j) {
        T temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }
    //泛型使用在返回值中
     public <T> T get(T[] ts) {
         return ts[ts.length / 2];
     }
}

通配符
public static void fun(List<?> list) {…}

带有上边界的通配符
public static void fun(List<? extends Number> list) {…}
fun(new ArrayList<Integer>());//ok
fun(new ArrayList<Double>());//ok
fun(new ArrayList<String>());//不ok

带有下边界的通配符
public static void fun(List<? super Integer> list) {…}
fun(new ArrayList<Integer>());//ok
fun(new ArrayList<Number>());//ok
fun(new ArrayList<Object>());//ok
fun(new ArrayList<String>());//不ok


 
原文地址:https://www.cnblogs.com/Xmingzi/p/8717059.html