Effective Java笔记(二)

3、类与接口

15、使类和成员的可访问性最小化

  • 尽可能地使每个类或者成员不被外界访问。
  • 让类具有公有的静态final数据域,或者这种域的访问方法,通常是错误的。(将其变为私有,并提供一个公有的不可变的列表)
    private static final Object[] A_A= {1,2,3};
    //1
    public static final List<Object> values = Collections.unmodifiableList(Arrays.asList(A_A));
    //2
    public static final Object[] values(){
        return A_A.clone();
    }
  • Java9开始,一个模块就是一个包
  • 四个访问级别(私有,包私有,受保护的,公有的)

16、要在共有类而非公有域中使用访问方法

  • 如果类是包级私有的,或者私有的嵌套类,直接暴露它的数据域并没有本质的错误
  • 共有类永远都不应该暴露可变的域。

17、使可变性最小化

  • 使类成为不可变类的五条规则
    • 不要提供任何会修改对象状态的方法(设值方法)
    • 保证类不会被扩展。(恶意子类 假装对象状态改变,防止子类化,一般声明类 final的)
    • 声明所有域都是final的
    • 声明所有的域都为私有的
    • 确保对于任何可变组件的互斥访问
  • 不可变对象本质上使线程安全的,它们不要求同步。
  • 不可变类真正唯一缺点是:对于每个不同的值都需要一个单独的对象。
  • 构造器应该创建完全初始化的对象,并建立所有的约束关系,不要在构造器或者静态工厂方法之外再提供公有的初始化方法。

18、复合优先于继承

  • 与方法调用不同的是,继承打破了封装性。(超类的实现可能随者发行版本变化,子类可能会遭受到破坏)
  • 不扩展现有的类,而是在新的类中增加一个私有域,它引用现有类的一个实例。

19、要么设计继承并提供文档说明,要么禁止继承

  • 该类必须要有文档说明它可覆盖的方法的自用性。
  • 构造器绝不能调用可被覆盖的方法。

20、接口优先于抽象类

  • 现有的类可以很容易被更新,以实现新的接口。
  • 接口是定义mixin(混合类型)的理想选择。

21、为后代设计接口

  • Java8之后,接口增加了缺省实现 通过defualt关键字。

22、接口只用于定义类型

  • 常量接口模式(一个接口只包含静态的final域,每个域都导出一个常量)是对接口的不良使用。
  • 当类实现接口时,接口就充当可以引用这个类的实例的类型。

23、类层次优于标签类

24、静态成员类优于非静态成员类

  • 嵌套类分为四种:静态成员类,非静态成员类,匿名类,局部类;除了第一种之外,其他三种都称为内部类。
  • 如果声明成员类不要求访问外部实例,就要始终把修饰符static放在它的声明中。
  • 匿名类在使用的同时被声明和实例化。
  • 局部类,在方法内部定义类。

25、限制源文件为单个顶级类

  • 永远不要把多个顶级类或者接口放在一个源文件中。

4、泛型

26、请不要使用原生态类型

  • 每一种泛型都定义一种原生态类型,例如 List 相对应的原生态类型是List;
  • 如果使用原生态类型,就失掉了泛型在安全性和描述性方面的所有优势。
  • 如果是像List这样的原生态类型,就会失掉类型安全性,但是如果使用像List这样的参数类型,就不会。
  • ?无限制的通配符类型
    在这里插入图片描述

27、消除非受检的警告

  • 参考 29中的代码: @SuppressWarnings(“unchecked”)

28、列表(List)优先于数组

  • 数组和泛型相比,有两个很重要的不同点,
    • 数组是协变的泛型是可变的
    • 数组是具体化的,泛型是擦除来实现的
  • 在某些情况下,即使某个对象不是数组的基类型,我们也可以把它赋值给数组元素。这种属性叫做协变 。例如:Object[] =new Long [l ] ;

29、优先考虑泛型

在这里插入图片描述

  • 考虑泛型则 new E()会有错误;此错误有两种解决方法
    • elements = (E[]) new Object[数组长度]; (优先使用,但会导致堆污染,因为数组运行时数据类型和编译时数据类型不一致)
    • 把E[] 改为Object[]类型,用的时候**@SuppressWarnings(’'unchecked”) = (E) e l ements[–size];**
//JDK部分源码 java.util.Vector.toArray实现
 @SuppressWarnings("unchecked")
    public synchronized <T> T[] toArray(T[] a) {
        if (a.length < elementCount)
            return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

        System.arraycopy(elementData, 0, a, 0, elementCount);

        if (a.length > elementCount)
            a[elementCount] = null;

        return a;
    }
	//上中的Arrays.copyOf()
    @HotSpotIntrinsicCandidate
    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

30、优先考虑泛型方法

  • 静态工具方法尤其适合泛型化
  • 声明类型参数的类型参数列表,处于方法的修饰符及其返回值之间
  • public static < E> Set< E> union(Set< E> sl, Set< E> s2) {方法体…}, 类型参数列表< E> ,返回类型Set< E>
  • public static <E extends Comparable E max(Collection c]; 其中<E extends Comparable 可以读作 针对每个可以与自身相比较的类型E;

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

  • 为了获得最大限度的灵活性,要在表示生产者或者消费者的输入参数上使用通配符类型
    • 如果参数化类型表示一个 T 生产者,就使用 <? extends T>;
    • 如果它表示一个 T 消费者, 就使用 <? super T> ;
  • 不要使用通配符作为返回类型
  • PESC原则:PESC = producer-extens , consumer -super.
  • comparable和comparator都是消费者;

32、谨慎并用泛型和可变参数

  • 将值保存在泛型可变参数数组中是不安全的;
  • 显式创建泛型数组是非法的 ,泛型可变参数声明方法是合法的 ,由于泛型可变参数声明方法实践用处比较大,允许了这一矛盾现象的存在。
  • SafeVarargs注解是通过方法的设计者做出承诺,说明这是类型安全的;不要随意用**@SafeVarargs**对方法注解,除非它是真正安全的;
  • 对于每一个带有泛型可变参数或者参数化类型的方法,都要用@SafeVarargs 进行注解;
  • 允许另一个方法访问一个泛型可变参数数组是不安全的;
  • 泛型可变参数在下列条件是安全的:
    • 1、它没有在可变参数数组中保存任何值;
    • 2、它没有对不被信任的 ;
    • 以上两个条件只要有任何一条被破坏,就要立即修正它;

    static <T> T[] toArray(T...args){
        return args;
    }

    static <T> T[] pickTwo(T a, T b,T c){
        switch (ThreadLocalRandom.current().nextInt(2)){
            case 0: return toArray(a,b);
            case 1: return toArray(a,c);
        }
        throw new AssertionError();
    }

    public static void main(String[] args) {
        /**
         * java.lang.ClassCastException 报错
         * 编译器在pickTwo返回值做了一个隐藏的转换 String[] 转换失败了
         * 允许另一个方法访问一个泛型可变参数数组是不安全的;
         */
        String[]  strings = pickTwo("goog", "fast","aaaaa");
        System.out.println(strings[0]);
    }

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

  • 将键(key)进行参数化而不是将容器(container)参数化。然后将参数化的键提交给容器来插入或者获取值,用泛型系统来确保值的类型与它的键相符。
public class demo_33 {
    private Map<Class<?>, Object> fa = new HashMap<>();
    public <T> void putFa(Class<T> type,T instance){
        fa.put(Objects.requireNonNull(type),instance);
    }
    public <T> T getFa(Class<T> type){
        return type.cast(fa.get(type));
    }
    public static void main(String[] args) {
        final demo_33 demo_33 = new demo_33();
        demo_33.putFa(String.class,"java");
        demo_33.putFa(Integer.class,1);
        final String fa = demo_33.getFa(String.class);
        System.out.println(fa);   
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值