考虑用静态构造方法代替构造器的好处:



1、静态构造方法有名字



    BigInteger.probablePrime(int, int, Random)比 new BigInteger(int, int, Random)更加清楚,从名字知道返回可能是素数。



    如果没有名字,将来给别人调用时,对方往往不知道该用哪个。



2、可以不必在每次调用时重新创建一个新对象



    其实就是享元模式和单例模式



3、可以返回原类型的任何子类型对象。



    这样可以使API变得更加简洁



    这里可以引申到“服务提供者框架模式”,类似于JDBC



4、创建参数化类型实例时,代码变得更简洁



    比如Map<String, List<String>> map = new HashMap<String, List<String>>();



    如果JDK有提供如下方法的话:



 public static <K, V> Map<K, V> newInstance(){

       return new HashMap<K,V>();

 }

可以直接Map<String, List<String>> map  = newInstance();

   不过现在的JDK还没有这个方法。



 



考虑用静态构造方法代替构造器的坏处:



1、由于使用静态构造方法,会把原来的构造器去掉,造成这个类将无法被继承。



    不过这样倒也正好鼓励使用复合,而非继承。



2、它与其他普通的静态方法没有区别,文档或者一些工具,无法自动区分出这是构造方法。



    如果有人要查这个类的构造方法,将很难找。



 



 



 



参数多的时候,并且有些参数是可选的,builder模式更好



 



 



关于单例模式的强化:



传统的单例模式会被反射破坏掉,可以在构造器里计数,如果创建第二次则抛异常。



传统的单例模式会在序列化和反序列化之后变成两个,需要重写readResolve方法,返回原来的单例



 



单例模式的最佳方法:单元素枚举,可以解决上述两个问题。



 



 



避免创建不必要的对象:



1、比如,String s = new String("abc"); 应该改成 String s = "abc";



2、更倾向于使用静态构造器,比如:Boolean.valueOf(String)替代new Boolean(String),因为前者内部有复用对象,后者肯定会产生一个新对象。



3、明知不会改变的对象,要复用。比如判断时间是否落在某个起止时间之间,这里的起止时间是固定的,不需要每次判断时生成。



4、Map的keySet每次返回的是同一个Set,所以产生多个也没害处,却也是没有必要的。



5、优先使用基本类型(int),虽然包装类(Integer)用起来和基本类型几乎无差别,但其中隐式的包装和解包装会比较耗性能。



 



 



WeakHashMap : 当key被除了map本身引用之外,再无别的地方引用时,该key会被自动删除。



 



缓存以及回调等容易引起内存泄漏的地方,推荐使用WeakHashMap,弱引用的方式。



 



 



大部分情况下,避免使用finalizer方法:



1、因为finalizer方法被执行的时间是不确定的,甚至有可能根本不执行。



    比如在finalizer方法里做关闭文件的动作是错误的,因为对象失去引用后到执行finalizer的时间不确定,所以文件不会被及时关闭。



2、finalizer在不同JVM上执行的时机也未必相同。



    有可能在开发测试时的JVM上表现很好,但到了现场的JVM表现就很差,不稳定。



3、System.gc与System.runFinalization只能增加finalizer被执行的机会,但仍然是不确定的。



4、System.runFinalizationOnExit以及Runtime.runFinalizersOnExit能保证finalizer一定被执行,但这两个方法有致命缺陷,已经被废弃。



5、未被捕获的异常在finalizer过程中抛出是会被忽略的,甚至连警告都不会打印出来。



6、使用finalizer有一个非常严重的性能损失,创建和销毁对象比原来慢很多



 



不使用finalizer,可以使用显示的终结方法,典型的比如InputStream的close方法,要求调用者必须在结束时调用。



但finalizer可以充当显示终结方法的"安全网",在调用者忘记调用显示终结方法时,可以在finalizer里执行,因为这个时候调用者已经忘记了,即使finalizer的执行很不稳定,那也比没有关闭一些资源要好。比如FileInputStream就是采用这种“安全网”。



 



finalizer的另一个合理的用途是,对本地对象(native object)的回收资源,本地对象比较特殊,垃圾回收器是不会回收本地对象,所以需要调用finalizer来回收非关键资源。