《Effective Java》第一章——创建和销毁对象

2017-03-08  本文已影响0人  Slience无言

内容摘引自《Effective Java》(第二版,机械工业出版社)

第一条:考虑用静态工厂方法代替构造器

这样做的好处

静态工厂方法的缺点

静态方法的惯用名称

服务提供者框架

定于:多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来。
这是一个静态工厂方法的实例
服务提供者框架包含四个部分

第二条:遇到多个构造器参数是要考虑用构建器

当一个实体有多个属性,而有的属性是非必需的那么在创建实例的时候可能会有多个构造函数可供选择,举例来说如下

package com.myclass;

public class OldPerson {
    private int age;
    private String name;
    private double weight;
    private String hobby;
    public OldPerson(int age, String name, double weight, String hobby) {
        // TODO Auto-generated constructor stub
        this.age = age;
        this.name = name;
        this.weight = weight;
        this.hobby = hobby;
    }
    
    //当weight和hobby不是必须的时候,我们在创建OldPerson就需要这样
    public OldPerson(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

如果有很多个参数那么构造函数就可能会有很多,可能会在使用的时候不小心颠倒了两个参数或者别的小问题,所以这种重叠构造器模式是可以的,但是当有许多参数的时候,客户端代码会很难编写,并且难以阅读。

更好地方法

package com.myclass;

public class Person {
    private int age;
    private String name;
    private double weight;
    private String hobby;
    
    public static class Builder {
        //必填参数
        private String name;
        
        //选填参数,设置默认值
        private int age = 0;
        private double weight = 0.0;
        private String hobby = "写bug";
        
        //设置必填参数
        public Builder (String name) {
            this.name = name;
        }
        
        //设置非必填参数
        public Builder age(int age) {
            this.age = age;
            return this;
        }
        public Builder weight(int weight) {
            this.weight = weight;
            return this;
        }
        public Builder hobby(String hobby) {
            this.hobby = hobby;
            return this;
        }
        
        public Person build() {
            return new Person(this);
        }
    }
    
    public Person(Builder builder) {
        // TODO Auto-generated constructor stub
        age = builder.age;
        name = builder.name;
        weight = builder.weight;
        hobby = builder.hobby;
    }
}

这样当我们使用的时候只需要这样

     Person person = new Person.Builder("Slience爱学习").weight(120).hobby("看书").build();

就可以了(虽然我用的比较多的是JavaBean模式)

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

(这一条没怎看懂)

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

我们知道当类中没有显式的构造器的时候,系统会自动生成一个缺省的构造器,当我们想要让一个类不能被实例的时候(比如说一些工具类),我们可以自己写一个构造函数,并把构造函数设置为私有的,这样就不会创建这个实例了,举例来说就是

package com.myclass;

public class MyClass {
    public static String say() {
        return "Hello World";
    }
    private MyClass() {
        // TODO Auto-generated constructor stub
    }
}

这样我们就创建不了MyClass实例,而只能使用它的say方法了。

第五条:避免创建不必要的对象

String str = "Hello World";
String str2 = new String("Hello World");

str相对于str2效率要高,因为在创建对象的时候"Hello World"已经是一个对象了,没有必要在用一层new String包裹起来再创建一个对象。
再举一个例子

        long start = System.currentTimeMillis();
        long sum = 0L;
        for(long i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }
        System.out.println(sum);
        System.out.println("耗时:" + (System.currentTimeMillis() - start));

        long start = System.currentTimeMillis();
        Long sum = 0L;
        for(long i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }
        System.out.println(sum);
        System.out.println("耗时:" + (System.currentTimeMillis() - start));

两者的执行耗时是不一样的,后者使用Long的耗时更大,因为要将i转成Long给sum加上,这意味着程序创造了不必要的很多个Long实例,造成了更多的耗时。

第六条:消除过期的对象引用

(原书是一个栈增长再减少的例子),减少掉的元素可能不会被垃圾回收,在极端情况下可能会造成内存泄漏。这是因为栈内部维护者这些对象的过期应用。
过期应用是指永远也不会被解除的引用。
解决这种问题的办法也很简单,那就是当对象引用过期的时候清空这些引用就可以了。

        String[] strs = {"星期一","星期二","星期三","星期四"};
        //如果要取出最后一个,应该这样
        String str = strs[strs.length-1];
        strs[strs.length-1] = null;
        System.out.println(str);

这样做的好处是当你不小心错误的解除引用,程序会报空指针异常而不是悄咪咪的运行下去。

第七条:避免使用终结方法

终结方法finalizer的线程优先级比其他应用程序的线程要低,如果要使用finalizer去结束一个一个比较有限的资源,比如说打开很多个文件的描述符(原文如此,可能是指explorer这样的东东吧),当你想要关掉它的时候再打开新的,因为优先级低所以可能先去打开新的然后旧的没有去关掉,关掉的速度比打开的速度低造成了资源的占用。比较常见的终结方法有InputStream、java.sql.Connention中的colse方法。
显示终结方法通常与try-finally结合起来使用,确保及时终止。
终结方法前使用try-finally显示终结的好处

上一篇 下一篇

猜你喜欢

热点阅读