为什么java中没有可选的公共构造函数?

Gop*_*ala 30 java constructor optional java-8

为什么Optional有类似的方法of()ofNullable()不是公共构造函数?

Ste*_*cek 37

来自Joshua Bloch有效的Java,第2章.创建和销毁对象,1项:

考虑静态工厂方法而不是构造函数

为什么?

静态工厂方法的一个优点是,与构造函数不同,它们具有名称.

使用静态工厂方法,我们可以在方法定义中指定一些实例化行为.这使得API更易于使用,并且我们阻止客户端调用错误的构造函数.

例如:在Optional.ofNullable- >我们允许传递null值以实例化Optional,Optional.of不允许使用null值并抛出异常.我们不能在这里使用构造函数.

private Optional(T value) {
    this.value = Objects.requireNonNull(value); //this throws NullPointerException
}
public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
}
public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
} 
Run Code Online (Sandbox Code Playgroud)

另一个优点(已经提到):

静态工厂方法的第二个优点是,与构造函数不同,它们不需要在每次调用时创建新对象.

在Optional中,空值仅实例化一次,然后存储在静态字段中,当程序需要空值时,该值将被重用.

private static final Optional<?> EMPTY = new Optional<>(); //instantiate value when program starts

public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY; //return stored value when requested
    return t;
}
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记:名称`of`和`ofNullable`不仅记录了这两个工厂的不同语义,它们也使它们成为可能,因为我们有两个具有相同类型签名的方法,因此需要不同的名称来声明它们在同一个班.由于构造函数没有名称,因此不可能使用相同的参数类型声明其中两个. (8认同)

Min*_*inn 21

原因实际上非常简单:一个空的可选是一个静态常量,以提高内存效率.如果使用了构造函数,则必须每次为常见案例创建一个新实例.

public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}
Run Code Online (Sandbox Code Playgroud)


use*_*900 10

可选是没有任何构造函数的基于值的类

没有可访问的构造函数,而是通过工厂方法实例化,这些方法不会对返回的实例的身份做出承诺

  • OP知道这一点.他在问为什么会这样. (14认同)
  • 不,我想他问为什么Optional的设计者选择不向Optional添加公共构造函数.回答那个Optional是一个值类,因此没有公共构造函数不回答问题,恕我直言. (13认同)
  • @JBNizet:我认为它确实在技术上回答了这个问题,但是打开了其他问题:"什么是价值等级","价值等级有什么优势".如果它还包含那些重要的信息,那么这个答案会更好. (2认同)

dav*_*xxx 9

因为当可能的实例化情况已知时,工厂方法应该优于公共构造函数.
它使API更易于用于客户端类.
除了工厂方法允许决定是否应该在每次调用时创建一个实例.
在这种情况下,Optional.empty()将值缓存为不可变的是有意义的.