为什么 java.time.YearMonth 进入决赛 class?
Why was java.time.YearMonth made a final class?
我计划写一个 class extends java.time.YearMonth
的目的是使用一种方法扩展 YearMonth
使我能够流式传输 LocalDate
YearMonth
:
public class ExtendedYearMonth extends YearMonth {
public Stream<LocalDate> days() {
LocalDate firstOfMonth = this.atDay(1);
LocalDate lastOfMonth = firstOfMonth.with(TemporalAdjusters.lastDayOfMonth());
return firstOfMonth.datesUntil(lastOfMonth);
}
}
好吧,当我发现 YearMonth
是一个 final class
⇒ final class
es 是不可扩展的 .
我当然可以写一个这样的 class
public class ExtendedYearMonth {
private YearMonth yearMonth;
// parameterized constructor, getters and setters omitted for brevity
public Stream<LocalDate> days() {
LocalDate firstOfMonth = this.yearMonth.atDay(1);
LocalDate lastOfMonth = firstOfMonth.with(TemporalAdjusters.lastDayOfMonth());
return firstOfMonth.datesUntil(lastOfMonth);
}
}
但这不是我想要的,因为它需要我实例化一个 YearMonth
和一个 ExtendedYearMonth
只是为了 stream
(和 filter
,主要目的) LocalDate
特定年份的特定月份。
JavaDocs of YearMonth
只是说明 那 它是 final
,而不是 为什么 它是 final
:
public final class YearMonth
...
YearMonth is an immutable date-time object that represents the combination of a year and month.
...
为什么 YearMonth
变成了 final
?
或更准确地说:final class YearMonth
比 class YearMonth
有什么好处?
我想不出任何理由...
我知道,回答这个问题需要深入了解可能在 www 某处 public 的设计决策,但不幸的是,我没有这种洞察力,我也没有目前已找到来源。
在 Kotlin 中,这无关紧要,因为可以编写扩展函数而不必继承 class
。这是 Kotlin 的一个很好的特性,但是 Java 没有这个(目前),我拒绝为此写一个包装器 class。
我还可以问为什么这样的方法在 YearMonth
中不可用,或者当 LocalDate
在 Java 9 中得到 datesUntil
时没有添加,但是将是单个 post 中的第二个问题,通常不赞成(并反对或反对),因此我稍后可能会在另一个 post.
中提出这个问题
我当前的解决方案是 public static Stream<LocalDate> daysOf(YearMonth yearMonth)
,它执行上述代码的操作,但我必须将实例传递给 static
方法,而不是直接使用它的方法。这符合我的要求,但它仍然不是我认为接近完美的解决方案。
因为 class 的实例保证 不可变。
如果允许 subclasses 则无法保证。
来自YearMonth class documentation:
* {@code YearMonth} is an immutable date-time object that represents the combination
* of a year and month.
The documentation of YearMonth
确实这么说了,但是是间接的:
This is a value-based class; use of identity-sensitive operations (including reference equality (==
), identity hash code, or synchronization) on instances of YearMonth
may have unpredictable results and should be avoided.
而 value-based 说:
Value-based Classes
Some classes, such as java.util.Optional
and java.time.LocalDateTime
, are value-based. Instances of a value-based class:
- are final and immutable (though may contain references to mutable objects);
- have implementations of
equals
, hashCode
, and toString
which are computed solely from the instance's state and not from its identity or the state of any other object or variable;
- make no use of identity-sensitive operations such as reference equality (
==
) between instances, identity hash code of instances, or synchronization on an instances's intrinsic lock;
- are considered equal solely based on
equals()
, not based on reference equality (==
);
- do not have accessible constructors, but are instead instantiated through factory methods which make no committment as to the identity of returned instances;
- are freely substitutable when equal, meaning that interchanging any two instances
x
and y
that are equal according to equals()
in any computation or method invocation should produce no visible change in behavior.
A program may produce unpredictable results if it attempts to distinguish two references to equal values of a value-based class, whether directly via reference equality or indirectly via an appeal to synchronization, identity hashing, serialization, or any other identity-sensitive mechanism. Use of such identity-sensitive operations on instances of value-based classes may have unpredictable effects and should be avoided.
这里没有明确说明,但是 subclassing 会与这些点相矛盾,因为它会导致实例代表相同值的可能性(根据 baseclass' 状态),但不能自由替换,当它们不具有相同的类型时。此外,即使 class 不是 final
,仅提供返回未指定身份实例的工厂方法的概念也不允许 subclasses,因为 subclasses 需要一个可访问的构造函数。
您可能会看到 value-based classes 等同于原始值;你不能子class一个int
,所以你不能子class一个YearMonth
,因为它只代表一个特定的值(只是强类型)和所有YearMonth
表示相同值的实例应该是相同的,无论是由不同的对象实例表示还是由单个实例表示。这使通往未来的道路在 Java.
中具有真实值类型
我计划写一个 class extends java.time.YearMonth
的目的是使用一种方法扩展 YearMonth
使我能够流式传输 LocalDate
YearMonth
:
public class ExtendedYearMonth extends YearMonth {
public Stream<LocalDate> days() {
LocalDate firstOfMonth = this.atDay(1);
LocalDate lastOfMonth = firstOfMonth.with(TemporalAdjusters.lastDayOfMonth());
return firstOfMonth.datesUntil(lastOfMonth);
}
}
好吧,当我发现 YearMonth
是一个 final class
⇒ final class
es 是不可扩展的 .
我当然可以写一个这样的 class
public class ExtendedYearMonth {
private YearMonth yearMonth;
// parameterized constructor, getters and setters omitted for brevity
public Stream<LocalDate> days() {
LocalDate firstOfMonth = this.yearMonth.atDay(1);
LocalDate lastOfMonth = firstOfMonth.with(TemporalAdjusters.lastDayOfMonth());
return firstOfMonth.datesUntil(lastOfMonth);
}
}
但这不是我想要的,因为它需要我实例化一个 YearMonth
和一个 ExtendedYearMonth
只是为了 stream
(和 filter
,主要目的) LocalDate
特定年份的特定月份。
JavaDocs of YearMonth
只是说明 那 它是 final
,而不是 为什么 它是 final
:
public final class YearMonth
...
YearMonth is an immutable date-time object that represents the combination of a year and month.
...
为什么 YearMonth
变成了 final
?
或更准确地说:final class YearMonth
比 class YearMonth
有什么好处?
我想不出任何理由...
我知道,回答这个问题需要深入了解可能在 www 某处 public 的设计决策,但不幸的是,我没有这种洞察力,我也没有目前已找到来源。
在 Kotlin 中,这无关紧要,因为可以编写扩展函数而不必继承 class
。这是 Kotlin 的一个很好的特性,但是 Java 没有这个(目前),我拒绝为此写一个包装器 class。
我还可以问为什么这样的方法在 YearMonth
中不可用,或者当 LocalDate
在 Java 9 中得到 datesUntil
时没有添加,但是将是单个 post 中的第二个问题,通常不赞成(并反对或反对),因此我稍后可能会在另一个 post.
我当前的解决方案是 public static Stream<LocalDate> daysOf(YearMonth yearMonth)
,它执行上述代码的操作,但我必须将实例传递给 static
方法,而不是直接使用它的方法。这符合我的要求,但它仍然不是我认为接近完美的解决方案。
因为 class 的实例保证 不可变。
如果允许 subclasses 则无法保证。
来自YearMonth class documentation:
* {@code YearMonth} is an immutable date-time object that represents the combination
* of a year and month.
The documentation of YearMonth
确实这么说了,但是是间接的:
This is a value-based class; use of identity-sensitive operations (including reference equality (
==
), identity hash code, or synchronization) on instances ofYearMonth
may have unpredictable results and should be avoided.
而 value-based 说:
Value-based Classes
Some classes, such as
java.util.Optional
andjava.time.LocalDateTime
, are value-based. Instances of a value-based class:
- are final and immutable (though may contain references to mutable objects);
- have implementations of
equals
,hashCode
, andtoString
which are computed solely from the instance's state and not from its identity or the state of any other object or variable;- make no use of identity-sensitive operations such as reference equality (
==
) between instances, identity hash code of instances, or synchronization on an instances's intrinsic lock;- are considered equal solely based on
equals()
, not based on reference equality (==
);- do not have accessible constructors, but are instead instantiated through factory methods which make no committment as to the identity of returned instances;
- are freely substitutable when equal, meaning that interchanging any two instances
x
andy
that are equal according toequals()
in any computation or method invocation should produce no visible change in behavior.A program may produce unpredictable results if it attempts to distinguish two references to equal values of a value-based class, whether directly via reference equality or indirectly via an appeal to synchronization, identity hashing, serialization, or any other identity-sensitive mechanism. Use of such identity-sensitive operations on instances of value-based classes may have unpredictable effects and should be avoided.
这里没有明确说明,但是 subclassing 会与这些点相矛盾,因为它会导致实例代表相同值的可能性(根据 baseclass' 状态),但不能自由替换,当它们不具有相同的类型时。此外,即使 class 不是 final
,仅提供返回未指定身份实例的工厂方法的概念也不允许 subclasses,因为 subclasses 需要一个可访问的构造函数。
您可能会看到 value-based classes 等同于原始值;你不能子class一个int
,所以你不能子class一个YearMonth
,因为它只代表一个特定的值(只是强类型)和所有YearMonth
表示相同值的实例应该是相同的,无论是由不同的对象实例表示还是由单个实例表示。这使通往未来的道路在 Java.