为什么 LocalDate、LocalTime 和 Stream 对象使用工厂方法 of() 而不是构造函数?

Why LocalDate, LocalTime and Stream objects use a factory method of() instead of a constructor?

为什么LocalDateLocalTimeStream等对象使用工厂方法of()而不是构造函数?

我找到了为什么应该使用工厂方法而不是 new 的解释。这个答案给出了很多原因,但唯一与 Java Date/Time API 相关的是:

unlike constructors, they are not required to create a new object each time they’re invoked

由于 LocalDateLocalTime 是不可变的,使用工厂并重用现有对象而不是每次都创建一个新对象可能是有意义的。

这就是为什么像LocalDateLocalTime这样的对象是用工厂方法(即LocalDate.of())创建的原因吗?还有其他原因吗?

此外,Stream 对象是可变的。为什么使用工厂方法(Stream.of())来创建Stream

Why a factory method (Stream.of()) is used to create a Stream?

使用工厂方法意味着您无需知道所使用的确切 class。这是一个很好的例子,因为 Stream 是一个接口,你不能创建一个接口的实例。

来自 Stream.of

的来源
/**
 * Returns a sequential {@code Stream} containing a single element.
 *
 * @param t the single element
 * @param <T> the type of stream elements
 * @return a singleton sequential stream
 */
public static<T> Stream<T> of(T t) {
    return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}

/**
 * Returns a sequential ordered stream whose elements are the specified values.
 *
 * @param <T> the type of stream elements
 * @param values the elements of the new stream
 * @return the new stream
 */
@SafeVarargs
@SuppressWarnings("varargs") // Creating a stream from an array is safe
public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}

注意:这些方法会调用其他工厂方法。

你可以看到根据它的调用方式你会得到不同的结构。你不需要知道这个或那个最终的 class 创建的是 ReferencePipeline.Head

+1 彼得的回答。

使用工厂方法的另一个原因是它们的行为类似于 "named constructors"。

比如LocalDate有6个静态工厂方法(至少,我这里可能没说完):

  • of(int year, int/Month month, int dayOfMonth)(两个重载)
  • ofEpochDay(long epochDay)
  • ofYearDay(int year, int dayOfYear)
  • parse(CharSequence text)
  • parse(CharSequence text, DateTimeFormatter formatter)

我认为通过将这些作为单独命名的方法,而不是一堆参数类型非常相似的构造函数,可以更清楚地理解各种参数的含义;您几乎可以猜到工厂方法的参数应该是什么,而如果它们是 "unnamed" 构造函数,您实际上可能必须阅读 Javadoc(震惊恐怖)。

诚然,of 是这些名称中最不清晰的 - 可能需要 ofYearMonthDayOfMonth - 但是,我怀疑这是最常用的工厂方法,而且它太杂乱了一直输入那个长名字。


如果您还没有读过,Effective Java 第 2 版 的第 1 项是关于为什么以及何时更喜欢静态工厂方法而不是构造函数。我这里说的"named constructor"优势其实是Bloch强调的第一个优势