当前位置: 代码迷 >> 综合 >> 【Effective Java】 第1章:序言,第2章:创建和销毁对象
  详细解决方案

【Effective Java】 第1章:序言,第2章:创建和销毁对象

热度:91   发布时间:2024-02-10 18:25:28.0

第1章:序言

第2章:创建和销毁对象

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

一、静态工厂方法的优势

1、静态工厂方法有名字。

2、不必在每次调用静态工厂方法的时候都创建一个对象。

3、静态工厂方法可以返回类型的任何子类型的对象。

这样我们在选择返回对象的类时就有了更大的灵活性。

这种灵活的一种应用是,API可以返回对象,同时又不会使对象的类变成共有的。以这种方式隐藏实现类会使API变得非常简洁。这种技术适用于基于接口的框架,因为这种框架中,接口为静态工厂方法提供了自然返回类型。

Java8仍要求接口的所有静态成员都必须是共有的。

在Java9中允许接口有私有的静态工厂方法,但是静态域和静态成员类仍然是共有的。

4、所返回的对象的类可以随着每次调用而发生变化,这取决于静态工厂方法的参数值。

5、方法返回的独享所属的类,在编写包含该静态工厂方法的类时可以不存在。

这种灵活的静态工厂方法构成了服务提供者框架的基础,例如JDBC的API。

二、静态工厂方法的优缺点

1、类如果不含有公有的或受保护的构造器,就不能被子类化。

2、程序员很难发现它们。

三、静态工厂方法的惯用名称

1、from,类型转换方法

它只有单个参数,返回该类型的一个相对应的实例。

Date date = Date.from(instant);

2、of,聚合方法

带有多个参数,返回该类型的一个实例,把它们合并起来。

Set<Rank> faceCards = EnumSet.of(JACK,QUEEN,KING);

3、valueOf

比from和of更繁琐的一种替代方法。

BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);

4、instance或者getInstance,返回的实例是通过方法的参数来描述的。

StackWalker luke = StackWalker.getInstance(options);

5、create或者newInstance,和instance和getInstance一样,但create和newInstance能够确保每次调用都返回一个新的实例。

Object newArray = Array.newInstance(classObject,arrayLen);

 6、getType,像getInstance一样,但是在工厂方法处于不同类中的时候使用。Type表示工厂方法所返回的对象类型。

FileStore fs = Files.getFileStore(path);

7、newType,像newInstance一样。

8、type,getType和newType的简版

四、总结

简而言之,静态工厂方法和共有构造器都各有好处,我们需要理解它们各自的长处。

静态工厂方法更加合适,因此切忌第一反应就是提供公有的构造器,而不考虑静态工厂。

第2条:遇到多个构造器参数时要考虑使用构建器

静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。

重叠构造器可行,但是当许多参数的时候,客户端代码会很难编写并且难以阅读。

JavaBeans模式

先调用无参构造器来创建对象,然后调用setter方法来设置每个必要的参数。

JavaBeans模式是我常用的方式,但是JavaBeans也有着很严重的缺点。因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。类无法通过检验构造器参数的有效性来保证一致性。

幸运的是,还有第三种替代方法。它既能像重叠构造器模式的安全性,又能保证像JavaBeans模式那样的可读性。这就是建造者模式。

package com.guor.effective.chapter2.worker;public class Worker {private int id;private String name;private int age;private int sex;private String school;private String address;public static class Builder{private int id;private String name;private int age = 18;private int sex = 1;private String school = "辽宁石油化工大学";private String address = "辽宁省大连市高新园区";public Builder(int id, String name) {this.id = id;this.name = name;}public Builder age(int val){age = val;return this;}public Builder sex(int val){sex = val;return this;}public Builder school(String val){school = val;return this;}public Builder address(String val){address = val;return this;}public Worker build() {return new Worker(this);}}public Worker(Builder builder){int id = builder.id;String name = builder.name;int age = builder.age;int sex = builder.sex;String school = builder.school;String address = builder.address;}@Overridepublic String toString() {return "Worker{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", sex=" + sex +", school='" + school + '\'' +", address='" + address + '\'' +'}';}
}

 

package com.guor.effective.chapter2.worker;public class Test {public static void main(String[] args) {Worker worker = new Worker.Builder(1,"郭晓彤").age(1).sex(1).school("中铁诺德幼儿园").address("中铁诺德滨海花园").build();System.out.println(worker.toString());}
}