隐藏静态创建方法背后的构造函数?

The*_*eLQ 19 java

我最近发现了一种在Google GuavaProject Lombok中创建对象的新实例的有趣方法:隐藏静态创建方法背后的构造函数.这意味着new HashBiMap()你可以做而不是做HashBiMap.create().

我的问题是为什么?隐藏构造函数有什么好处?对我来说,我认为这样做绝对没有优势,它似乎打破了基本的对象创建原则.因为开始创建一个对象new Object(),而不是一些Object.createMe()方法.这几乎就像为创建方法创建一个方法.

你这样做会得到什么?

Nam*_*ter 27

您可能更喜欢静态工厂方法而不是公共构造函数的原因有很多.您可以阅读Effective Java,Second Edition中的第1项,以进行更长时间的讨论.

  1. 它允许方法返回的对象类型与包含该方法的类的类型不同.实际上,返回的类型可以取决于参数.例如,EnumSet.of(E)如果emum类型的元素非常少,则返回不同的类型,如果枚举类型包含许多元素,则返回不同的类型(编辑:在这种特殊情况下,提高枚举不具有多个元素的常见情况的性能)
  2. 它允许缓存.例如,Integer.valueOf(x)默认情况下,如果多次调用相同的值x,则返回相同的对象实例,如果x介于-128和127之间.
  3. 它允许您拥有命名构造函数(如果您的类需要许多构造函数,这可能很有用).例如,参见中的方法java.util.concurrent.Executors.
  4. 它允许您创建一个概念上简单但实际上非常强大的API.例如,静态方法Collections隐藏了许多类型.Collections他们可以创建许多公共类,而不是拥有许多静态方法的类,但对于熟悉该语言的人来说,这将更难以理解或记忆.
  5. 对于泛型类型,它可以限制您需要执行的输入量.例如,List<String> strings = new ArrayList<String>()您可以这样做而不是键入Guava List<String> strings = Lists.newArrayList()(该newArrayList方法是泛型方法,并且推断了泛型类型).

因为HashBiMap,最后一个原因是最有可能的.


Kir*_*oll 7

这通常是因为create()方法实际实例化的类可能与调用方法的类型不同.即工厂模式,其中create()方法返回适合给定当前上下文的特定子类.(例如,当currrent环境是Windows时返回一个实例,而当它是Linux时返回另一个实例).

  • 你也不能模拟构造函数(换句话说,从模拟的角度来看,静态工厂方法的灵活性不比公共构造函数低) (2认同)

oks*_*ayt 6

与构造函数不同,静态方法可以具有方法名称.这是我最近写的一个有用的课程:

/**
 * A number range that can be min-constrained, max-constrained, 
 * both-constrained or unconstrained.
 */

public class Range {
  private final long min;
  private final long max;
  private final boolean hasMin;
  private final boolean hasMax;

  private Range(long min, long max, boolean hasMin, boolean hasMax) {
    // ... (private constructor that just assigns attributes)
  }

  // Static factory methods

  public static Range atLeast (long min) {
    return new Range(min, 0, true, false);
  }

  public static Range atMost (long max) {
    return new Range(0, max, false, true);
  }

  public static Range between (long min, long max) {
    return new Range(min, max, true, true);
  }

  public static Range unconstrained () {
    return new Range (0, 0, false, false);
  }
}
Run Code Online (Sandbox Code Playgroud)

你不能只使用构造函数,因为atLeast并且atMost将具有完全相同的签名(它们都需要一个长).