• effective Java 第三版学习笔记


     

     

    创建对象类型的

    1,静态工厂方法代替构造器

    • 静态工厂方法有名称,不容易混乱他的作用
    • 不必再每次调用他的时候创建实例,创建实例的代价是高的,可以重复利用缓存的对象
    • 静态工厂甚至能返回子类对象,例如在接口上(Java8 )的静态方法上,返回一个直接可以用的类
    • 根据参数值,决定不同的返回类型(貌似和上面有点像
    • 返回的类型,可以在写静态工厂时候不存在(貌似用在rpc方面)
    • 缺点
    • 如果不包含公有或包含的构造器,就不能让子类实例化
    • javadoc不能很好解释
    • ps
    • vauleOf,转换方法
    • instance或者getInstance,通过方法参数获得实例,但不能说每次实例都是一样的,A a =  A.getInstance(option)
    • create或者createInstance,通过静态方法获得实例,每次都说新的实例
    • getType,在不同类中返回不同的对象,type可以是其他意思,比如getA,getB
    • newType,和上面一样,返回新的实例

    2,遇到多个构造器参数的时候,使用构建器

    • 构建器有同样的参数列表
    • 构建器构造函数写必须的参数,后面再添加可选的参数
    • build方法返回实例的引用

    3,用枚举强化单例模式

    4,在一些静态工具类中,将构造方法私有化,不能abstract抽象化,别人还以为你是专门用来继承的

    5,不要用单例和静态工具类来实现一个或多个资源的类(他们都只能假设有一种资源)(静态工具类不能用状态),因为资源的行为会影响类的行为,应该将资源交给工厂(spring),通过他们进行依赖注入来创建类

    6,避免创建不必要的对象

    • string
    • 像解析token,正则表达式,这些,缓存创建好的对象
    • 自动装箱问题,尽量使用基本类型

    7,消除过期的对象引用

    • 像栈这种需要自己维护一些数组的需要引用指空来防止内存泄漏
    • 缓存也会内存泄漏,当缓存的生命周期由该键的外部引用决定时,可以用weakhashmap

    8,-

    9,使用try-with-resource 代替try- catch

    所有对象通用的方法

     10,equal的一些性质,(几个特性,没认真记住

    •  重写equal前重写hashcode
    • 不要重写时候换了入参对象,因为这样是重载不是重载

    11,重写equal前重写hashcode

    12,始终覆盖tostring,尽可能输出又用的信息

    13,谨慎重写clone(未看)

    14,实现comparable接口的时候,比较值避免使用《》,用装箱基本类型的类的compare方法,或者Comparator接口中的比较器

    类和接口

    15,类和成员的可访问性最小化(未怎么看

    16,要在公有类而非公有域使用访问方法(set,get

    17,可变性最小,为了成为不可变类的条件

    • 不要设置方法
    • 类被final修饰,(不可被扩展
    • 域都是被final修饰
    • 域都是私有的
    • 不被其他引用指向
    • 缺点
    • 每次都要new一个,改进,一些计算的域适当可变

    18,复合优于继承

    • 继承的时候是否满足is a的关系
    • 在使用继承来实现功能的时候,超类方法可能又自己方法的自用性,当你不够了解超类的实现的时候,重写的方法可能在别的地方被调用了,所有一般又组合的方式,写个装饰者模式

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

    • 必须又文档说明可覆盖的方法和自用性
    • 比如在一个remove方法里面,说明他调用了equal了方法,那么重写equal这个方法的时候就会得到注意
    • 构造器不能调用重写的方法,毕竟超类在构造的时候,重写方法还没实现
    • clone和serializable的实现方法也不能调用重写方法
    • 必须要用,可以抽象出来一个私有方法调用

    20,接口优于抽象类,如果是个很重要的接口,考虑提供骨架类,例如:AbstractList

    21,为后代设计接口,虽然Java8又default,但也要慎重设计接口

    22,常量不应该定义在接口

    23,类层次优于标签结构,很无聊,就是不要写太多具体的东西和模板在同个类中,用继承来层次化他

    24,解释了内部类,和外部类没有一一对应的关系的时候可以选择static

    25,单个源文件为单个顶级类,想多个的时候,请使用静态类,防止编译的时候发生错误,少编译了类

    泛型

    26,不要使用原生态类型,collection这些,用泛型,这样可以尽早检查出错误

    27,受检警告很重要,尽量不要删除它,如果要删除,请确定再最小范围,还有注释为什么要删除

    28,用list代替数组

    29,优先考虑使用泛型

    30,优先考虑泛型方法

    31,利用限定符提升api的灵活性

    • extend 作为生产者
    • super 作为消费者
    • 当方法中没有用到具体的泛型,入参可以考虑使用?,但方法中需要插入或者删除,封装多一层的泛型

    32,谨慎并用泛型和可变参数(没看懂

    33,优先考虑类型安全的异构容器(没看懂

    枚举和注解

    34,优先使用常量对比于枚举

    35,不要依赖枚举本来的ordinary值,自己set值

    36,用EnumSet代替位域

    37,用EnumMap代替序数索引

    38,用接口模拟可扩展的枚举

    39,注解优于命名模式(看了题目,没深入看

    40,坚持使用@Override注解,防止自己写了重载而不是重写这种错误

    41,用标记接口来定义类型

    lambda和stream

    42,lambda代替匿名类

    43,方法引用优于lambda

    44,写函数接口的时候,看看是否又官方库类,比如predicate,function,consumer,还有基于基本类型的接口

    45,慎重使用stream

    • 统一转换元素序列
    • 过滤元素序列
    • 利用单个操作(如添加,连接,计算最小值)合并元素顺序
    • 分组 
    • 搜索满足某些条件

    46,优先选择stream无副作用的函数,就是用collectors里面的

    47,stream优先使用collectior作为返回类型(看不懂

    48,谨慎,少用stream的并发流

    方法

    49,检查方法入参的有效性

    50,必要时进行保护性拷贝,别把需要的引用给暴露出去,要的话给他拷贝一个,如果你觉得这样伤害性能,就建议在安全环境下进行

    51,谨慎设计方法签名,名字参考jdk,参数用枚举代替Boolean

    52,慎用重载,重载是再编译期的,没有重写的在运行期再决定动作,可以考虑改接口名来,自动装箱也有问题remove(e),remove(int),确定传进去相同参数的时候,行为是一样的

    53,慎用可变参数

    54,返回数组和集合的时候,返回一个空的比null好,避免客户端代码出错

    55,使用optional,当一个方法无法给出返回值的时候,有两种选择,

    • null,但会让客户端代码有npe
    • 抛出异常,异常栈有代价的
    • 返回optional,强迫客户端思考,有点像受检异常

    56,为api写javadoc

    Java通用编程(一些细枝末节

    57,局部变量作用域最小化

    58,foreach 代替for

    • 除了用remove方法
    • 除了不需要全部遍历
    • 除了两个集合同时遍历

    59,使用官方库类,不然就用第三方

    60,要准确数据用bigDecimal,long(不超过18),int(不超过9)代替float,double

    61,尽量使用基本类型

    • 自动装箱带来的性能问题
    • 自动拆箱带来的npe
    • 集合和其他容器用装箱

    62,如果其他类型更加适合,就不用字符串,(很虚

    63,拼接字符串使用stringBuilder

    64,通过接口引用对象(面向抽象编程?

    65,接口优于反射(不懂

    66,谨慎使用本地方法

    67,谨慎地进行优化(不要浪费时间搞有的没的

    68,改名规范

    •   不可实例化的工具类加s结尾,collections,collectors
    • 返回Boolean的用isxxxx
    • 转换对象类型,tostring,toxxx

    69,异常不可以作为控制语句来混用

    70,可以回复的异常使用受检异常

    71,避免使用受检异常(不太会

    72,使用官方异常

     73,抛出与抽象对应的异常,高层次的异常吃掉低层次的异常,然后抛出高层次的异常,这就叫异常的转换

    74,每个抛出的异常都应该又文档支持

    75,细节异常的信息(不太很理解

    76,出现异常的时候,保留原子性(原来的状态

    • 在改变对象状态前抛出异常
    • 在拷贝对象上修改

    77,永远不要忽略异常

    并发

    78,共享变量需要同步(废话?)(不用thread。stop,用Boolean让自己的线程停止自己的线程

    79,把同步区域做到最小

    80,使用executor,stream,task代替手写线程

    81,使用aqs框架的工具代替手写notify,wait

    82,为线程安全添加必要的文档

    83,慎用延迟初始化,有必要用双重锁检测

    84,不要依赖线程调度器(不太理解

    序列化

    85,用json和protobuf代替Java序列化

    86,谨慎实现serilianize接口(不太理解

    87,考虑使用自定义的序列化形式(不太理解

  • 相关阅读:
    【剑指offer】判断二叉树是否为平衡二叉树
    【剑指offer】数字在排序数组中出现的次数
    八大排序方法汇总(选择排序,插入排序-简单插入排序、shell排序,交换排序-冒泡排序、快速排序、堆排序,归并排序,计数排序)
    约瑟夫环问题-循环链表VS数组
    告别2014,你是否感谢这一年的自己?
    浅谈WEB页面提速(前端向)
    HTML5- Canvas入门(七)
    浅谈WEB安全性(前端向)
    是时候搁置Grunt,耍一耍gulp了
    前端神器avalonJS入门(二)
  • 原文地址:https://www.cnblogs.com/vhyc/p/10859986.html
Copyright © 2020-2023  润新知