EffectiveJava心得一

来源:互联网 发布:java是后端吗 编辑:程序博客网 时间:2024/06/09 16:38

强制不能生成实例

如果不希望使用new 关键词创建对象,则可以把构造函数的访问权限设置为private,尤其是那些只包含静态方法的工具类。

静态工厂


使用静态工厂方法代替new 关键词创建对象,工厂方法通过不同的命名可以根据需要返回不同的子类对象,而且如果需要可以不用每次都创建新对象。 

静态工厂方法的优点:

  • 静态方法有名称

具有适当名称的静态工厂方法更易于阅读,而构造器的参数本身没有确切描述被返回的对象。如:BigInteger(int, int, Random)返回的BigInteger可能为素数,如果使用BigInteger.probablePrime的静态方法来表示,就更为清楚。

  • 不必在每次调用类时都创建一个新对象

对于不可变类可以使用预先构建好的实例,或则将构建好的实例缓存起来,进行重新复用。

  • 可以返回原返回类型的任何子类型的对象

我们在选择返回对象的类时,使用静态工厂方法就更有灵活性。这种灵活性的一种应用是API可以返回对象,同时又不会使对象的类变成公有的。这种方式隐藏实现类会使API变得非常简洁。 
在Java的集合框架的接口实现中,几乎所有这些实现都通过静态工厂方法在一个不可实例化的类中导出,所有返回对象的类都是非公有的。 
公有的静态工厂方法所返回的对象的类不仅可以是非公有的,还可以随着参数值的不同而每次调用也发生变化。只要是已声明的返回类型的子类型,都是允许的。

  • 在创建参数化类型实例时,代码更加简洁

调用参数化类的构造器时,即使类型参数很明显,也必须指明,这通常要求你接连两次提供类型参数。例如创建HashMap的实例。 
随着类型参数变得越来越长,冗长的说明也很快变得痛苦起来,但是使用静态工厂方法,编译器就可以替你找到类型参数,这被称作类型推导
Google的Guava集合框架中提供了类似的Lists.newArrayList的方法。可以试着比较下面两个代码:

Map<StringList<String>> map = new HashMap<StringList<String>>();
  • 1

下面的写法显然更简便。


静态工厂方法的缺点:
1、一个类如果不含公有的或者受保护的构造器,就不能被子类化。
2、静态工厂方法与其他静态方法实际上没有任何区别。Javadoc工具不会区别出静态工厂方法,所有静态工厂方法命名应当遵守标准的命名习惯来弥补这一劣势。惯用名称有:valeuOf,of,getInstance,getType,newType等。


Builders


当构造方法中有超过三个参数时,可以考虑使用builder去构建对象,可能有些繁琐,但是这样易于扩展且可读性更强。

避免可变

不可变指一个对象在其生命周期中保持相同的值,在创建时就设置来所有需要的值。这样做的好处很多,比如线程安全、可共享等。

但是不能所有对象都是不可变的,所以要尽力做到(比如定义private final成员变量,final类)。

静态内部类

如果创建内部类时不依赖外部类,一定要定义为静态类,否则内部类的实例会持有外部类实例的引用。

使用泛型

我们应该感谢Java的类型安全(对比JS),尽量保证编译期的类型安全:

不要忘记方法的参数和返回值可以使用泛型:

还可以使用受限的通配符来限制类型的上下界:

返回空值

如果有一个方法的返回值类型是List/collection,不要返回null,可以返回一个空collection:

不要使用"+"操作String

当只有少数String时,可以考虑使用 "+",当数量较多时,考虑使用StringBuilder:

异常恢复

我不支持为了指示错误而抛出异常,如果你想这样做,最好保证程序可以从异常恢复:


原创粉丝点击