为什么 java.time 使用 'of' 而不是 'new' 作为日期?
Why does java.time use 'of' instead of 'new' for dates?
在Java8的新日期包中,我们从使用“new Date()”改为"LocalDate.of()".
Date d = new Date(year, month, dayOfMonth); //Old way
LocalDate d2 = LocalDate.of(year, month, dayOfMonth); //new way
当您想要一个新对象时,通常会使用 new
关键字。这是创建新对象的直观方法。
有时,当您需要具有延迟初始化的单例时,您可以使用静态方法来获取实例。在这种情况下,您必须将其命名为 getInstance()
,以便开发人员知道会发生什么。
这种新语法使代码不那么直观。它迫使您学习如何处理特定对象,而不是简单地使用它们。
进行此更改是否有充分的理由?
有一个名为 Fluent interface
的设计模式,它允许 "chaining" 种方法,请参阅 Wikipedia。它应该非常可读,模仿自然语音 ("get x of y with z")。
在您的示例中并不是特别链接(假设它只包含一个方法调用),但在任何地方都使用相同的范例是有意义的。
通常静态工厂方法比构造函数更受欢迎,原因有几个,
- 它们有一个名字,这使您的代码更具可读性。
- 静态工厂方法可以有协变 return 类型,但是
构造函数不能。这允许您的 API 用户使用接口,而不是实现,让您有更多空间在未来的版本中更改具体类型。它还减少了 API 的概念表面积。
- 与构造函数不同,静态工厂方法可以做某些事情
优化。相反,每次调用构造函数时,
您希望它 return 一个新对象。例如,查看
静态工厂方法的实现
Collections.emptyList();
public static final List EMPTY_LIST = new EmptyList<>();
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
它急切地创建一个单例列表,并在每次调用时 return 保存它,从而节省了使用构造函数时会发生的不必要的开销。
由于上述原因,在今天的编程中,静态工厂比构造函数更受青睐。但是,您仍然可以根据情况在构造函数中使用 new
关键字。
new
存在问题:您的代码取决于具体 class。因此changing/evolving代码是一个更难的任务。
工厂更易于管理,因为 (1) 用户代码不依赖于具体类型 (2) 选择具体类型的代码在一个地方。那么最后的代码就多了secure/evolvable,等等
getInstance()
不是一个好的工厂名称,它更像是一个单例方法的名称。 "get"不是为了创造什么,只是为了得到已经存在的东西。 createInstance
或 create
对于工厂来说更为明确(其中许多,即使在 Java 中也被称为这样 - 检查 createImage
等)。但是,唉,由于@slaw 在评论中明确指出的原因,您需要更精确地帮助用户在参数语义之间进行选择,例如 createFromYears
、createFromMinutes
等。这可能有点冗长,那么 of
似乎是一个很好的折衷方案。最后,使用 of*()
比 createImage()
更容易(恕我直言)有很多参数来解释什么是参数...
在Java8的新日期包中,我们从使用“new Date()”改为"LocalDate.of()".
Date d = new Date(year, month, dayOfMonth); //Old way
LocalDate d2 = LocalDate.of(year, month, dayOfMonth); //new way
当您想要一个新对象时,通常会使用 new
关键字。这是创建新对象的直观方法。
有时,当您需要具有延迟初始化的单例时,您可以使用静态方法来获取实例。在这种情况下,您必须将其命名为 getInstance()
,以便开发人员知道会发生什么。
这种新语法使代码不那么直观。它迫使您学习如何处理特定对象,而不是简单地使用它们。
进行此更改是否有充分的理由?
有一个名为 Fluent interface
的设计模式,它允许 "chaining" 种方法,请参阅 Wikipedia。它应该非常可读,模仿自然语音 ("get x of y with z")。
在您的示例中并不是特别链接(假设它只包含一个方法调用),但在任何地方都使用相同的范例是有意义的。
通常静态工厂方法比构造函数更受欢迎,原因有几个,
- 它们有一个名字,这使您的代码更具可读性。
- 静态工厂方法可以有协变 return 类型,但是 构造函数不能。这允许您的 API 用户使用接口,而不是实现,让您有更多空间在未来的版本中更改具体类型。它还减少了 API 的概念表面积。
- 与构造函数不同,静态工厂方法可以做某些事情
优化。相反,每次调用构造函数时,
您希望它 return 一个新对象。例如,查看
静态工厂方法的实现
Collections.emptyList();
public static final List EMPTY_LIST = new EmptyList<>();
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
它急切地创建一个单例列表,并在每次调用时 return 保存它,从而节省了使用构造函数时会发生的不必要的开销。
由于上述原因,在今天的编程中,静态工厂比构造函数更受青睐。但是,您仍然可以根据情况在构造函数中使用 new
关键字。
new
存在问题:您的代码取决于具体 class。因此changing/evolving代码是一个更难的任务。
工厂更易于管理,因为 (1) 用户代码不依赖于具体类型 (2) 选择具体类型的代码在一个地方。那么最后的代码就多了secure/evolvable,等等
getInstance()
不是一个好的工厂名称,它更像是一个单例方法的名称。 "get"不是为了创造什么,只是为了得到已经存在的东西。 createInstance
或 create
对于工厂来说更为明确(其中许多,即使在 Java 中也被称为这样 - 检查 createImage
等)。但是,唉,由于@slaw 在评论中明确指出的原因,您需要更精确地帮助用户在参数语义之间进行选择,例如 createFromYears
、createFromMinutes
等。这可能有点冗长,那么 of
似乎是一个很好的折衷方案。最后,使用 of*()
比 createImage()
更容易(恕我直言)有很多参数来解释什么是参数...