Java 是否有可能延长Joda的期末考试时间? 我真的很喜欢JoDA时间,但我遇到了一些我认为是个问题。我想扩展一些类,特别是DateTime、LocalDate和LocalDateTime。但它们被标记为“最终”
我发现了一个非常古老的线程,其中解释为确保类保持不变的一种方法 我在这里还发现了一个线程,讨论了是否需要将Java类标记为final以确保不变性 无论如何,我发现不能扩展这些类是一个主要的限制。除了下载源文件并修改它们之外,还有什么办法可以创建这些类的扩展版本吗 编辑-讨论: 扩展类的能力是面向对象编程中最强大、最有用的概念之一。这总是有用的。一个类的作者不可能100%确信他/她的超级复制器类在扩展到涵盖任何人都无法预见的用例时,对某些程序员来说不会更有用 Joda时间类被标记为“final”的明显原因是为了确保某人不可能创建可变的扩展类,并将其用于依赖于Joda时间对象的不可变的现有程序。因此,在某种程度上,将这些类标记为“final”是因为缺少一种Java语言机制,该机制允许将类标记为“不可变”,因此它们可以被扩展,但前提是扩展类也标记为“不可变” 因此,考虑到Java中缺少“不可变”关键字,我可以理解Joda Time的作者希望避免这种情况 以下解决方案可行吗?我们可以有一个从LocalDateNonFinal派生LocalDate的结构吗?LocalDate是一个标记为“final”的空类。所有功能都在LocalDateNonFinal中 因此,如果您确实想要扩展LocalDate类,并且只打算在您自己的程序中使用扩展的类,那么您可以改为扩展LocalDateNonFinal,并将其称为MyLocalDate。这不会使其他模块暴露于您可能犯的错误,因为它们仍然需要LocalDate,并且不接受LocalDateNonFinal或您的MyLocalDate 这可以与试图教育想要扩展这些类的程序员相结合,如果他们意外地创建了可变版本,并且仍然将其视为不可变的,则警告他们可能出现的问题。并指出这些扩展类将不可用于其他需要常规(“最终”)类的模块Java 是否有可能延长Joda的期末考试时间? 我真的很喜欢JoDA时间,但我遇到了一些我认为是个问题。我想扩展一些类,特别是DateTime、LocalDate和LocalDateTime。但它们被标记为“最终”,java,jodatime,Java,Jodatime,我发现了一个非常古老的线程,其中解释为确保类保持不变的一种方法 我在这里还发现了一个线程,讨论了是否需要将Java类标记为final以确保不变性 无论如何,我发现不能扩展这些类是一个主要的限制。除了下载源文件并修改它们之外,还有什么办法可以创建这些类的扩展版本吗 编辑-讨论: 扩展类的能力是面向对象编程中最强大、最有用的概念之一。这总是有用的。一个类的作者不可能100%确信他/她的超级复制器类在扩展到涵盖任何人都无法预见的用例时,对某些程序员来说不会更有用 Joda时间类被标记为“final”的
另外,我会在几天后发布我的变通解决方案,当我完全确定的时候。到目前为止,我对其中两个答案投了赞成票——谢谢你的评论和建议。我目前倾向于使用类似于包装器的解决方案,正如Dmitry Zaitsev所建议的那样。如果您真的需要扩展类,您可以从这里获得源代码: 分叉它们,将它们标记为非最终的,并扩展它们
否则您无法扩展最终类。如果您确实需要扩展类,您可以从这里获得源代码: 分叉它们,将它们标记为非最终的,并扩展它们
否则您就不能扩展final类。不可能扩展任何标记为final的类,并且分叉这些类是不实际的。除您自己的代码外,代码中的对象将期望看到Joda类,并将验证它们得到的是什么,您将无法传递您自己的版本。所以使用forking的最佳情况是,您将有一组对象供自己使用,您必须将它们转换为Joda或java8,以便与其他代码一起使用。此外,您的分叉版本不会从将来对原始类所做的任何修复中获益,除非您继续将修复复制到您自己的版本中。另一个问题可能是Joda类和您自己的版本之间的比较可能不可传递,结果可能取决于调用它们的对象
您可以使用所有静态方法创建一个实用程序类,这些静态方法将接受一个Joda对象,执行您想要的任何额外功能并返回一个Joda对象。这类似于在apache commons或java.lang.Math中找到的StringUtil类。这样,您就避免了forking的维护,并且可以直接与库或框架代码一起使用。不可能扩展任何标记为final的内容,而且forking这些类也不实用。除您自己的代码外,代码中的对象将期望看到Joda类,并将验证它们得到的是什么,您将无法传递您自己的版本。所以使用forking的最佳情况是,您将有一组对象供自己使用,您必须将它们转换为Joda或java8,以便与其他代码一起使用。此外,您的分叉版本不会从将来对原始类所做的任何修复中获益,除非您继续将修复复制到您自己的版本中。另一个问题可能是Joda类和您自己的版本之间的比较可能不可传递,结果可能取决于调用它们的对象
您可以使用所有静态方法创建一个实用程序类,这些静态方法将接受一个Joda对象,执行您想要的任何额外功能并返回一个Joda对象。这类似于在apache commons或java.lang.Math中找到的StringUtil类。这样,您就避免了forking的维护,并且可以直接与库或框架代码一起使用。您可以将最终类包装到自己的类中,提供您想要的任何操作,并提供“view”方法,该方法将返回原始的Joda time对象。就像这样:
public class MyJodaExtension {
private final DateTime dateTime;
public MyJodaExtension(DateTime dateTime) {
this.dateTime = dateTime;
}
public boolean myOperation() {
return false; // or whatever you need
}
public DateTime asDateTime() {
return dateTime;
}
}
通过这种方法,您甚至可以使MyJodaExtension
可变并提供不同的
package com.Merlinia.MCopier_Main;
import org.joda.time.DateTime;
/**
* This common base class is used to provide a (mutable) wrapper for the (immutable) Joda-Time
* DateTime and LocalDateTime classes. It is used as the base class (super class, in Java
* terminology) for the DateTimeLocal and DateTimeUtc classes. This provides a somewhat kludgy way
* of extending the DateTime and LocalDateTime classes, since they can't be directly extended
* because they are marked "final".
*
* The only service provided by this class is that it contains a field which can contain the .Net
* DateTime "ticks" value that was used to create this object via MCopier deserialization. This is
* then used by MCopier serialization to provide an identical result if the object is round-tripped
* from .Net to Java and back again, although only if the associated DateTime or LocalDateTime
* object has not been updated. (If the DateTime or LocalDateTime object is updated then this field
* is set to Long.MIN_VALUE, and is no longer considered valid.) Sending an identical result back to
* .Net simplifies the testing program, as well as avoiding unnecessary loss of precision. (Joda-
* Time is only precise to the nearest millisecond. .Net DateTime ticks can, in theory, be precise
* to the nearest 100 nanoseconds.)
*/
public abstract class DateTimeCommon {
// See here: http://stackoverflow.com/questions/3706306/c-sharp-datetime-ticks-equivalent-in-java
private static final long CTicksAtEpoch = 621355968000000000L;
private static final long CTicksPerMillisecond = 10000;
private long _dotNetDateTimeTicks; // Long.MIN_VALUE means not valid
// Constructor for new object, not due to MCopier deserialization
public DateTimeCommon() {
_dotNetDateTimeTicks = Long.MIN_VALUE;
}
// Copy constructor
public DateTimeCommon(DateTimeCommon copyFrom) {
_dotNetDateTimeTicks = copyFrom._dotNetDateTimeTicks;
}
// Constructor used by MCopier deserialization
public DateTimeCommon(long dotNetDateTimeTicks) {
_dotNetDateTimeTicks = dotNetDateTimeTicks;
}
protected void indicateDotNetTicksNotValid() {
_dotNetDateTimeTicks = Long.MIN_VALUE;
}
// Method used by MCopier deserialization to compute the number of milliseconds in Java notation
// that corresponds to a long int containing a .Net DateTime value in "ticks". But note that
// although Java millis are normally always based on the UTC time zone, that the millis returned
// by this method in the case of a .Net DateTimeLocal value are not UTC-based; they are
// independent of time zone and represent a different instant in time for different time zones.
// See also here:
// http://stackoverflow.com/questions/3706306/c-sharp-datetime-ticks-equivalent-in-java
protected static long convertTicksToMillis(long dotNetDateTimeTicks) {
return
(dotNetDateTimeTicks - CTicksAtEpoch + CTicksPerMillisecond / 2) / CTicksPerMillisecond;
}
// Method used by MCopier serialization
protected long getAsDotNetTicks(DateTime jodaDateTime) {
if (_dotNetDateTimeTicks != Long.MIN_VALUE) {
return _dotNetDateTimeTicks;
}
return (jodaDateTime.getMillis() * CTicksPerMillisecond) + CTicksAtEpoch;
}
}
package com.Merlinia.MCopier_Main;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
/**
* This class provides a (mutable) wrapper for the (immutable) Joda-Time LocalDateTime class. See
* comments on the DateTimeCommon base class.
*
* All manipulation of this object should consist of a call to getJodaLocalDateTime() followed by
* manipulation of the LocalDateTime object, producing a new (immutable) LocalDateTime object,
* followed by a call to setJodaLocalDateTime().
*
* When doing MCopier serialization and deserialization from/to .Net DateTime "ticks" we do
* something a bit sneaky: We pretend that the ticks represent a UTC time, and we pretend that the
* associated Joda-Time LocalDateTime object also represents UTC time. Both of these pretences are
* (normally) false, but the end result is that it works. See also here:
* http://stackoverflow.com/questions/11665404/simplest-way-to-get-local-milliseconds-in-a-time-zone-with-joda-time
*/
public class DateTimeLocal extends DateTimeCommon {
private LocalDateTime _jodaLocalDateTime;
// Constructor for new object, not due to MCopier deserialization
public DateTimeLocal(LocalDateTime jodaLocalDateTime) {
super();
_jodaLocalDateTime = jodaLocalDateTime;
}
// Copy constructor
public DateTimeLocal(DateTimeLocal copyFrom) {
super(copyFrom);
_jodaLocalDateTime = copyFrom._jodaLocalDateTime;
}
// Constructor used by MCopier deserialization
public DateTimeLocal(long dotNetDateTimeTicks) {
super(dotNetDateTimeTicks);
_jodaLocalDateTime = new LocalDateTime(
DateTimeCommon.convertTicksToMillis(dotNetDateTimeTicks), DateTimeZone.UTC);
}
public LocalDateTime getJodaLocalDateTime() {
return _jodaLocalDateTime;
}
public void setJodaLocalDateTime(LocalDateTime jodaLocalDateTime) {
_jodaLocalDateTime = jodaLocalDateTime;
super.indicateDotNetTicksNotValid();
}
// Method used by MCopier serialization
public long getAsDotNetTicks() {
return super.getAsDotNetTicks(_jodaLocalDateTime.toDateTime(DateTimeZone.UTC));
}
}