提出问题

项目中如何使用对象???

解决问题

考虑用静态工厂方法代替构造器

例:

  1. public static Boolean valueOf(boolean b) {
  2. return (b ? Boolean.TRUE : Boolean.FALSE);
  3. }

静态方法和构造器相比优势:

  • 静态方法有名称,构造器没有:一个类只能有一个带有指定签名的构造器。如果需要2个,它们的参数列表只在参数类型的顺序上有所不同。这并不是个好主意。
  • 静态方法不必在每次调用它们的时候都创建一个新的对象。
  • 静态方法可以返回原返回类型的任何子类型的对象。例如:Java Collections的集合接口有32个便利实现,每种便利实现都对应一个类。
  • 静态方法在创建参数化类型实例的时候,它们使代码变得更加简洁。

Map

遇到多个构造器参数时要考虑构造器

重叠构造器模式:第一个构造器只有一个必要参数,第二个有一个可选参数,第三个有两个,以此类推,最后一个构造器有全部的可选参数。创建实例的时候,选择最短的列表参数的构造器,当有许多参数的时候,客户端代码会很难编写

参考高手文章:http://macrochen.iteye.com/blog/1113031

解决方法:采用构建器(Builder)

  1. public Class A{
  2. private int a;
  3. private int b;
  4. private int c;
  5. private int d;
  6. public static class Builder{
  7. // 这些是必要参数
  8. private final int a;
  9. private final int b;
  10. //这些是可选参数
  11. private int c;
  12. private int d;
  13. public Builder(int a, int b){
  14. this.a=a;
  15. this.b=b;
  16. }
  17. public Builder setC(int c){
  18. this.c = c;
  19. //注意是这里,这里,看过来,看过来
  20. return this;
  21. }
  22. public Builder setD(int d){
  23. this.d=d;
  24. return this;
  25. }
  26. public A build(){
  27. return new A(this);
  28. }
  29. private A(Builder builder){
  30. a = builder.a;
  31. b = builder.b;
  32. c = builder.c;
  33. d = builder.d;
  34. }
  35. }

使用:

  1. A a = new A.Builder(1, 2).setC(3).setD(4).build();

总结:

如果类的构造器或者静态工厂中具有多个参数, 设计这种类时, Builder模式就是一种不错的选择. 特别是大多数参数都是可选的时候. 与使用传统的重载构造器模式相比, 使用Builder模式的客户端将更易于阅读和编写.

用私有构造器或者枚举类型强化Singleton属性

Singleton指被实例化一次的类。

参考高手文章:http://www.cnblogs.com/rilley/archive/2012/10/24/2737597.html

例:

  1. //这种写法存在缺陷,可以利用反射的方式来实例化多个不同的实例
  2. //序列化和反序列换的时候也会出现多个不同的实例
  3. public class Elvis {
  4. public static final Elvis INSTANCE = new Elvis();
  5. private Elvis {}
  6. }

参考高手文章:http://blog.csdn.net/huangyuan_xuan/article/details/52193006

或者:

  1. public class Elvis {
  2. private staic final Elvis INSTANCE = new Envis();
  3. private Elvis() {}
  4. private static Elvis getInstance() {
  5. //开过来,这里很重要
  6. return INSTANCE;
  7. }
  8. }

或者:

  1. public enum Elvis{
  2. INSTANCE;
  3. public void invoke(){...}
  4. }

参考高手文章:http://callmegod.iteye.com/blog/1474441

  1. public enum MaYun {
  2. himself; //定义一个枚举的元素,就代表MaYun的一个实例
  3. private String anotherField;
  4. MaYun() {
  5. //MaYun诞生要做的事情
  6. //这个方法也可以去掉。将构造时候需要做的事情放在instance赋值的时候:
  7. /** himself = MaYun() {
  8. * //MaYun诞生要做的事情
  9. * }
  10. **/
  11. }
  12. public void splitAlipay() {
  13. System.out.println(“Alipay是我的啦!看你丫Yahoo绿眉绿眼的望着。。。”);
  14. }
  15. }
  16. CallMaYun.himself.splitAlipay();

单元素的枚举类型已经成为实现Singleton的最佳方法。

枚举:很好,不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。但是失去了类的一些特性,没有延迟加载,用的人也太少了~~

以后多推广推广单元素枚举这种更好的单例实现方式。在项目中的代码开始修改实施。

通过私有构造器强化不可实例化的能力

->对只有静态方法和域的类,主要用于把基本类型的值或数据类型上的相关方法组织起来(Math,Arrays),可以通过Collections的方法把实现特定接口的对象上的惊天方法组织起来,可以利用这种类把final类上的方法组织起来,以取代扩展该类的做法。

->此工具类是不希望被实例化的,实例化对他么有任何意义。然后我们如果不提供构造器,jvm会自己提供,那还是会被实例化,那么我们只要在类中提供一个私有的构造器就可以了,并添加注释说明。
这样带来的问题是不能子类化,因为子类要求要求super父类的构造函数。

避免创建不必要的对象

一般来说,最好能重用对象,而不是在每次需要的时候,就创建一个相同功能的对象,如果对象是不可变的,他就始终可以被重用。

例如

  1. //”ay & al” 本身就是一个对象,这样写的话,頻繁调用会造成成千上万不必要的String实例
  2. String s = new String(“ay & al”);

改进

  1. String s = "al & ay";

对于同时提供的静态工厂方法和构造器的不可变类,通常可以使用静态工厂方法,而不是构造器,以避免创建不必要的对象。

例如

  1. Boolean.valueOf(String)

优于

  1. Boolean(String)

要优先使用基本类型而不是装箱基本类型,要当心无意识的自动装箱。

例如

  1. public static void main(String[] args){
  2. Long sum = 0L;
  3. for(long i=0;i<Integer.MAX_VALUE;i++){
  4. sum + = i;//在这里不断的进行装箱和拆箱工作
  5. }
  6. System.out.println(sum);
  7. }

消除过期的对象引用

清空引用对象应该是一种例外, 而不是一种规范行为

以下三种情况要考虑会发生内存泄露:

  • 类自己申请内存管理
  • 缓存,易忘记管理,如WeakHashMap可以自动处理没有被外部引用的缓存项。一般利用后台线程定时清理,也可以类似LinkedHashMap使用removeEldestEntry在添加条目时清理。对于复杂的缓存,必须直接使用java.lang.ref
  • 监听器和其他回调,回调此时可以做成弱引用。

只要是类自己管理内存, 程序员就应该警惕内存泄露的问题.