Effective Java笔记

----------------------------------------------------创建和销毁对象

======================1.考虑用静态工厂方法代替构造器=======================
BigInteger bigInteger = BigInteger.ONE;
---静态工厂方法和其他的静态方法实际上没有区别 难区分 但是静态工厂是代替构造器的 所以
一定会返回一个这个类的实例 一些静态工厂方法的惯用名称
valueOf
of
getInstance
newInstance
getType
newType
======================2.遇到多个构造器参数的时考虑用构建起==================
不过感觉他们好像还是javabean用的比较多啊

// Builder Pattern - Pages 14-15
public class NutritionFacts { private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; private final int carbohydrate; private NutritionFacts ( Builder builder ) { servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; } public static class Builder { // Required parameters
        private final int servingSize; private final int servings; // Optional parameters - initialized to default values
        private int calories = 0; private int fat = 0; private int carbohydrate = 0; private int sodium = 0; public Builder ( int servingSize, int servings ) { this.servingSize = servingSize; this.servings = servings; } public Builder calories ( int val ) { calories = val; return this; } public Builder fat ( int val ) { fat = val; return this; } public Builder carbohydrate ( int val ) { carbohydrate = val; return this; } public Builder sodium ( int val ) { sodium = val; return this; } public NutritionFacts build () { return new NutritionFacts( this ); } } public static void main ( String[] args ) { NutritionFacts cocaCola = new NutritionFacts.Builder( 240, 8 ) .calories( 100 ).sodium( 35 ).carbohydrate( 27 ).build(); } }
======================3.用私有构造器或者枚举类型强化Singleton属性===============
Sinngleton指仅仅被实例化一次的类 有三种方式
//1.Singleton with public final field
public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis () {} public void leaveTheBuilding () { System.out.println( "Whoa baby, I'm outta here!" ); } // This code would normally appear outside the class!
    public static void main ( String[] args ) { Elvis elvis = Elvis.INSTANCE; elvis.leaveTheBuilding(); } } //2.Singleton with static factory
public class Elvis { private static final Elvis INSTANCE = new Elvis(); private Elvis () {} public static Elvis getInstance () { return INSTANCE; } // This code would normally appear outside the class!
    public static void main ( String[] args ) { Elvis elvis = Elvis.getInstance(); elvis.leaveTheBuilding(); } public void leaveTheBuilding () { System.out.println( "Whoa baby, I'm outta here!" ); } } //3.Enum singleton - the preferred approach
public enum Elvis { INSTANCE; public void leaveTheBuilding () { System.out.println( "Whoa baby, I'm outta here!" ); } // This code would normally appear outside the class!
    public static void main ( String[] args ) { Elvis elvis = Elvis.INSTANCE; elvis.leaveTheBuilding(); } }
======================4.通过私有构造器强化不可实例化的能力==================
一些只包含静态方法和静态域的类(一些工具类 util) 实例没有任何意义 但是在缺少显式构造器的
情况下 编译器会提供一个自动的无参默认构造器 所以我们让类包含私有的构造器 这样它就不能
被实例化了 副作用 不能被子类化
public class UtilityClass { // Suppress default constructor for noninstantiability
    private UtilityClass () { throw new AssertionError(); } }

======================5.避免创建不必要的对象
对于同时提供了静态工厂方法和构造器的不可变类 通常可以使用静态工厂方法
能重用的 创建好了之后不用改变的 可以加个静态块
要优先使用基本类型 小心无意识的自动装箱
不过也不要太吝啬创建对象 小对象的创建和销毁是非常廉价的 能提升程序的清晰性 简洁性和
功能性

======================6.消除过期的对象引用
java有垃圾回收 但是也要小心 无意识的对象保持
比如

public Object pop() { if (size == 0 ) { throw new EmptyStackException(); } return elements[--size]; }

elements[--size];这里其实没有消除过期引用 要再加 elements[size] = null;
清空对象引用是一种例外 而不是一种规范行为
不过也不要过分小心 如果在最紧凑的作用域范围内定义变量 就可以解决
当类自己管理内存 容易遭受内存泄漏问题

======================7.避免使用终结方法

----------------------------------------------------对于所有对象都通用的方法

======================8.覆盖equals时请遵守通用约定
最容易的解决方法就是 不覆盖equals方法
======================9.覆盖equals时总要覆盖hashcode
======================10.始终要覆盖toString
======================11.谨慎地覆盖clone
======================12.考虑实现Comparable接口

----------------------------------------------------类和接口

======================13.使类和成员的可访问性最小化
======================14.在公有类中使用访问方法而非公有域
多用get set field还是private不要直接设置成public
======================15.使可变性最小化
写set 的时候 想一想
下面的例子是一个控制可变性很小的例子 还有String 基本类型的包装类 都是不可变类
不可变对象比较简单 只有一种对象

public final class Complex { public static final Complex ZERO = new Complex( 0, 0 ); public static final Complex ONE = new Complex( 1, 0 ); public static final Complex I = new Complex( 0, 1 ); private final double re; private final double im; private Complex ( double re, double im ) { this.re = re; this.im = im; } public static Complex valueOf ( double re, double im ) { return new Complex( re, im ); } // Accessors with no corresponding mutators
    return 的是一个新的对象 所以没有改变它自己原来的对象 public Complex add ( Complex c ) { return new Complex( re + c.re, im + c.im ); } }

======================16.复合优先于继承
注意这里说的继承是具体类的继承 不是接口的继承
先说一下问题吧 你继承了之后 如果你不是覆盖了超类的所有方法 超类的实现细节不明了
public class InstrumentedHashSet < E > extends HashSet< E >
{ @Override public boolean add ( E e ) { addCount++; return super.add( e ); } @Override public boolean addAll ( Collection< ? extends E > c ) { addCount += c.size(); return super.addAll( c ); } }

实际上HashSet里吗的addAll方法 是用了add方法 所以这个代码看着是对的 其实 它的addAll方法
加了两次addCount(一次是调用覆盖的add的里面 一次是它自己写的)
还有就是你不覆盖 只添加新的方法扩展超类 看着安全一点 但后续超类可能会有同签名的方法

用组合避免这些问题
======================17.要么为继承而设计,并提供文档说明,要么就禁止继承
======================18.接口优于抽象类
======================19.接口只用于定义类型
======================20.类层次优于标签类
======================21.用函数对象表示策略
======================22.优先考虑静态成员类

----------------------------------------------------泛型

======================23.请不要在新代码中使用原生态类型
======================24.消除非受检警告
======================25.列表优先于数组
======================26.优先考虑泛型
======================27.优先考虑泛型方法
======================28.利用有限制通配符来提升API的灵活性
======================29.优先考虑类型安全的异构容器

----------------------------------------------------枚举和注解

======================30.用enum代替int常量
======================31.用实例域代替序数
======================32.用EnumSet代替位域
======================33.用EnumMap代替序数索引
======================34.用接口模拟可伸缩的枚举
======================35.注解优先于命名模式
======================36.坚持使用Override注解
======================37.用标记接口定义类型

----------------------------------------------------方法

======================38.检查参数的有效性
======================39.必要时进行保护性拷贝
======================40.谨慎设计方法签名
======================41.慎用重载
======================42.慎用可变参数
======================43.返回零长度的数组或者集合,而不是:null
======================44.为所有导出的API元素编写文档注释

----------------------------------------------------通用程序设计

======================45.将局部变量的作用域最小化
======================46.for-each循环优先于传统的for循环
======================47.了解和使用类库
======================48.如果需要精确的答案,请避免使用float和double
======================49.基本类型优先于装箱基本类型
======================50.如果其他类型更适合,则尽量避免使用字符串
======================51.当心字符串连接的性能
======================52.通过接口引用对象
======================53.接口优先于反射机制
======================54.谨慎地使用本地方法
======================55.谨慎地进行优化
======================56.遵守普遍接受的命名惯例

----------------------------------------------------异常

======================57.只针对异常的情况才使用异常
======================58.对可恢复的情况使用受检异常,对编程错误使用运行时异常
======================59.避免不必要地使用受检的异常
======================60.优先使用标准的异常
======================61.抛出与抽象相对应的异常
======================62.每个方法抛出的异常都要有文档
======================63.在细节消息中包含能捕获失败的信息
======================64.努力使失败保持原子性
======================65.不要忽略异常

----------------------------------------------------并发

======================66.同步访问共享的可变数据
======================67.避免过度同步
======================68.executor和task优先干线程
======================69.并发工具优先于wait和notify
======================70.线程安全性的文档化
======================71.慎用延迟初始化
======================72.不要依赖于线程调度器
======================73.避免使用线程组

----------------------------------------------------序列化

======================74.谨慎地实现Serializable接口
======================75.考虑使用自定义的序列化形式
======================76.保护性地编写readObject方法
======================77.对于实例控制,枚举类型优先于readResolve
======================78.考虑用序列化代理代替序列化实例

你可能感兴趣的:(Effective Java笔记)