Effective Java学习笔记---------泛型

本文探讨了Java中的泛型、有限通配符的应用,如何通过泛型方法提高代码的安全性和灵活性,以及在Stack类实例和方法中展示的具体实践。特别强调了使用通配符类型来适应不同类型参数的重要性,以及PECS原则在设计API时的指导作用。
摘要由CSDN通过智能技术生成

术语

参数化的类型:List<String>
实际类型参数:String
泛型:List<E>
形式类型参数:E
无限通配符类型:List<?>
原生态类型:List
有限制类型参数:<E extends Number>
递归类型限制:<T extends Comparable<T>>
有限制通配符类型:List<? extends Number>
泛型方法:static<E> List<E> asList(E[] a)
类型方法:String.class

不要使用原生态类型

泛型:声明中具有一个或多个类型参数的类 或接口

原生态类型会失去泛型在安全性和描述性方面的优势

消除非受检的警告,不能忽视

列表优于数组

优先考虑泛型

只要时间允许,就要把现有的类型都泛型化

泛型化类例子

package codeTemplate.effectiveJava.bean;

import java.util.ArrayList;
import java.util.List;

public class Stack<E> {
    private List<E> elements;
    private int size;

    public Stack() {
        elements = new ArrayList<>();
    }

    public void add(E e) {
        elements.add(e);
        size++;
    }

    public E pop() {
        size--;
        return elements.remove(0);
    }

    public static void main(String[] args) {
        Stack<String> stringStack = new Stack<>();
        stringStack.add("1");
        String element = stringStack.pop();
        System.out.println(element);
    }
}

优先考虑泛型方法

泛型方法的定义

修饰符 <T,E,…> 返回值类型 方法名(形参列表){
。。。。。。
}

修饰符与返回值类型中间的 泛型标识符 <T,E,…>,是 泛型方法的标志,只有这种格式声明的方法才是泛型方法。
泛型方法声明时的 泛型标识符 <T,E,…> 表示在方法可以使用声明的泛型类型。
与泛型类相同,泛型标识符可以是任意类型,常见的如T,E,K,V 等。
泛型方法可以声明为 static 的,并且与普通的静态方法是一样的。
    public static <E> E checkNullAndReturn(E o) {
        if (o == null) {
            throw new NullPointerException();
        }
        return o;
    }
   //使用
   String o = Stack.checkNullAndReturn("123");

利用有限通配符来提升API的灵活性

参数化类型是不变的,如List不是List的子类,List只能放String类型,不能转化成List

    public void addAll(List<? extends E> list) {
        elements.addAll(list);
    }

使用

        //E为Object
        Stack<Object> stringStack = new Stack<>();
        //可以接收String(Object的子类)
        stringStack.add("1");
        Object element = stringStack.pop();
        System.out.println(element);
        //可以接收List<Integer>(符合List<? extends Object>)
        stringStack.addAll(Arrays.asList(1,2));

注:

  1. 为了获得最大限度的灵活性,要在表示生产者或者消费者的输入参数上使用通配符类型
  2. PECS:producer-extends,consumer-super
  3. 所有的comparable和comparator都是消费者,Comparable<? super T>,Comparator<? super T>

谨慎并用泛型和可变参数

可变参数和泛型不能良好地合作

优先考虑类型安全的异构容器

常见泛型

Set Map<K,V>,ThreadLocal,AtomicReference,这些都是参数化了的容器,每个容器只能有固定数目的类型参数,可以将类型参数放在键上而不是容器上来避开这一限制。类型安全的异构容器,可以用Class对象作为键,如Map<Class<?>, Object>,其中

Class<?>是Class的无线通配符,表示可以是任意Class类型

类型令牌:当一个类的字面被用在方法中,来传达编译时和运行时的类型信息

    @Getter
    private Map<Class<?>, Object> favorites = new HashMap<>();
    
    public <E> void putFavorite(Class<E> type, E instance) {
        favorites.put(type, instance);
    }
    
    stringStack.putFavorite(String.class,"123");
    System.out.println(stringStack.getFavorites());
    //结果
    {class java.lang.String=123}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值