java - 如何在带有日期字段的java中使类不可变?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31846965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make a class immutable in java with date field in it?
提问by Mona Dhar
I have created an immutable class with a date field. How do I ensure that even the date field is immutable, since even if you make date field final you can still assign a different value to it later?
我创建了一个带有日期字段的不可变类。我如何确保即使日期字段也是不可变的,因为即使您将日期字段设为 final,您以后仍然可以为其分配不同的值?
回答by Codebender
In your getDate()
method, return a new Date()
instance, instead of the same instance.
在您的getDate()
方法中,返回一个new Date()
实例,而不是同一个实例。
public Date getDate() {
// Not correct.
return this.date; // This will make your class mutable.
// Instead use,
return new Date(this.date.getTime()); // This will make sure your date field cannot be changed.
}
回答by Basil Bourque
java.time
时间
Other Answers are correct that in showing strategies for fixing values within your objects.
其他答案是正确的,显示了在对象中修复值的策略。
Let me also recommend that you use the modern java.timeclasses rather than the terrible legacy classes. In place of Date
, use Instant
. In place of Calendar
, use ZonedDateTime
.
我还建议您使用现代java.time类而不是可怕的遗留类。代替Date
,使用Instant
. 代替Calendar
,使用ZonedDateTime
.
The java.timeclasses are designed as immutable objects.Methods such as plus…
, minus…
, to…
, and with
all produce a fresh object, leaving the original intact. The classes carry no settermethods.
该java.time类被设计成不可变对象。法如plus…
,minus…
,to…
,和with
所有的产品新的对象,离开原来的不变。这些类没有setter方法。
Bonus tip: In your own immutable classes, you may find it useful to follow the method naming patterns established by the java.timeclasses.
额外提示:在您自己的不可变类中,您可能会发现遵循java.time类建立的方法命名模式很有用。
About java.time
关于java.time
The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date
, Calendar
, & SimpleDateFormat
。
The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310。
Using a JDBC drivercompliant with JDBC 4.2or later, you may exchange java.timeobjects directly with your database. No need for strings nor java.sql.* classes.
使用符合JDBC 4.2或更高版本的JDBC 驱动程序,您可以直接与您的数据库交换java.time对象。不需要字符串或 java.sql.* 类。
Where to obtain the java.time classes?
从哪里获得 java.time 类?
- Java SE 8, Java SE 9, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android, the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植。
- 安卓
- 更高版本的 Android 捆绑实现 java.time 类。
- 对于早期的 Android,ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
回答by Saurabh
You can clone date object so that it cannot be modified
您可以克隆日期对象,使其无法被修改
public Date getDate (){
return (Date) this.date.clone ();
}
回答by Oliver
This is an example of a Bean(Class) with an immutable HAS-A Date Object.
这是具有不可变 HAS-A 日期对象的 Bean(Class) 示例。
import java.util.Date;
public class MyBean {
private Date date; // Immutable Date Step 1 Make Private
public MyBean(Date date)
{
// Immutable Date Step 2 If Set through Constructor then get a specialised (sub class) Date.
this.date= getImmutableDate(date); // THIS METHOD RETURNS AN IMMUTABLE DATE
}
public MyBean(){} // Allow Default Constructor
public Date getDate() {
return date;
}
// Immutable Date Step 3- Allow setting of date only once!!
public void setDate(Date date) {
if(this.date==null)
{
this.date= getImmutableDate(date);
}
}
/* Override all Setter methods of Date class. So even if user gets reference of Date Object it is not the original date object
* it would be a modified date object whose all setter methods do nothing*/
private Date getImmutableDate(Date date)
{
/* This is an Anonymous Inner Class that extends java.util.Date class, it overrides all the setter methods
* making the date object IMMUTABLE( i.e setXXX has no effect)
* */
date =new Date(date.getTime()){
private static final long serialVersionUID = 1L;
@Override
public void setYear(int year) {}
@Override
public void setMonth(int month) {}
@Override
public void setDate(int date) {}
@Override
public void setHours(int hours) {}
@Override
public void setMinutes(int minutes) {}
@Override
public void setSeconds(int seconds) {}
@Override
public void setTime(long time) {}
};
return date;
}
}
}
回答by Avinash
Here is the simple example of immutable
class in Java
这是immutable
类的简单示例Java
public final class Employee{
final String pancardNumber;
public Employee(String pancardNumber){
this.pancardNumber=pancardNumber;
}
public String getPancardNumber(){
return pancardNumber;
}
}
The above class is immutable because:
上面的类是不可变的,因为:
- The instance variable of the class is final i.e. we cannot change the value of it after creating an object.
- The class is final so we cannot create the subclass.
- There is no setter methods i.e. we have no option to change the value of the instance variable.
- 类的实例变量是最终的,即我们不能在创建对象后更改它的值。
- 类是最终的,所以我们不能创建子类。
- 没有 setter 方法,即我们无法更改实例变量的值。
These points makes this class as immutable. In case of Date
attribute, you can use constructor to set your date with every new object and import org.joda.time.DateTime
class. This is a better version than the java.util.Date
because it is immutable. Using a java.util.Date would be dangerous as it is a mutable class and we can't control the calling thread (which might modify it). Here is example.
这些点使这个类成为不可变的。在Date
属性的情况下,您可以使用构造函数为每个新对象和导入org.joda.time.DateTime
类设置日期。这是一个比 更好的版本,java.util.Date
因为它是不可变的。使用 java.util.Date 会很危险,因为它是一个可变类,我们无法控制调用线程(可能会修改它)。这是示例。
public final class Bill {
private final int amount;
private final DateTime dateTime;
public Bill(int amount, DateTime dateTime) {
this.amount = amount;
this.dateTime = dateTime;
}
public int getAmount() {
return amount;
}
public DateTime getDateTime() {
return dateTime;
}
}
回答by Joni
Use defensive copying. This means that if you have to pass the date to some other class, for example through a method parameter or returned from a method, you should make a copy.
使用防御性复制。这意味着如果您必须将日期传递给某个其他类,例如通过方法参数或从方法返回,您应该制作一个副本。
Making a copy of a Date is easy:
制作日期的副本很容易:
new Date(myDate.getting())
回答by Naveen Yadav
Identify the mutable instance variables(like date or hashmap) return new objects with copied content for all mutable objects. Immutable variables can be returned safely without extra effort.
识别可变实例变量(如日期或哈希图)返回带有所有可变对象复制内容的新对象。无需额外努力即可安全返回不可变变量。
See below example:
见下面的例子:
import java.util.Date;
public final class ImmutableClass
{
/**
* Integer class is immutable as it does not provide any setter to change its content
* */
private final Integer immutableField1;
/**
* String class is immutable as it also does not provide setter to change its content
* */
private final String immutableField2;
/**
* Date class is mutable as it provide setters to change various date/time parts
* */
private final Date mutableField;
//Default private constructor will ensure no unplanned construction of class
private ImmutableClass(Integer fld1, String fld2, Date date)
{
this.immutableField1 = fld1;
this.immutableField2 = fld2;
this.mutableField = new Date(date.getTime());
}
//Factory method to store object creation logic in single place
public static ImmutableClass createNewInstance(Integer fld1, String fld2, Date date)
{
return new ImmutableClass(fld1, fld2, date);
}
//Provide no setter methods
/**
* Integer class is immutable so we can return the instance variable as it is
* */
public Integer getImmutableField1() {
return immutableField1;
}
/**
* String class is also immutable so we can return the instance variable as it is
* */
public String getImmutableField2() {
return immutableField2;
}
/**
* Date class is mutable so we need a little care here.
* We should not return the reference of original instance variable.
* Instead a new Date object, with content copied to it, should be returned.
* */
public Date getMutableField() {
return new Date(mutableField.getTime());
}
@Override
public String toString() {
return immutableField1 +" - "+ immutableField2 +" - "+ mutableField;
}
}
For more details : http://www.javainterviewpoint.com/make-class-immutable-java/
更多详情:http: //www.javainterviewpoint.com/make-class-immutable-java/
回答by user1001
Only way to do this. Create a custom DateClass and Overrider the set** methods and dont provide any functionality to this methods.
做到这一点的唯一方法。创建一个自定义 DateClass 并覆盖 set** 方法,并且不为此方法提供任何功能。