假设我有一个类Comment,我有一个名为 commentDate 的私有字段,它是一个java.util.Date,并且有一个名为 getCommentDate 的getter。
为什么最好返回该日期的副本(返回新日期(commentDate.getTime()))而不是简单地返回该日期......
用户如何更改该日期的对象状态,因为它是一个getter而不是setter?
答案 0 :(得分:13)
由于java.util.Date
实施Cloneable
,您可以轻松克隆日期,如下:
public class DateTest {
private Date date;
public DateTest() {
}
public Date getDate() {
return (Date) date.clone();
}
public void setDate(Date date) {
this.date = (Date) date.clone();
}
}
答案 1 :(得分:7)
首先,请,请尽量避免使用getter和setter。如果你在同一个领域同时拥有它们,你几乎肯定会做错事。我不在乎Java专家告诉你什么。他们不知道他们在谈论什么。这不是OO的工作方式。 OO不是将字段访问转换为方法调用的make-work项目。这实际上并没有封装任何东西。
那说:如果你自己返回日期,那么调用代码会引用你的日期对象,并且可以使用它的完整界面。由于日期是可变对象,因此界面包含可以更改对象状态的内容。由于引用是您的日期,您的日期状态将会更改。调用代码如何得到日期并不重要(即“带有吸气剂”)。
答案 2 :(得分:5)
用户如何更改对象状态 那个日期,因为它是一个吸气剂,而不是 一个二传手?
轻松:
Comment comment = new Comment();
comment.getCommentDate().setTime(0); // now it's January 1, 1970 00:00:00 GMT.
答案 3 :(得分:2)
按照Tapas Bose的例子,我们可以使用JAVA 8来处理NULL情况:
public class DateTest {
private Date date;
public DateTest() {
}
public Date getDate() {
return Optional.ofNullable(date).map(Date::getTime).map(Date::new).orElse(null);
}
public void setDate(Date inputDate) {
this.date= Optional.ofNullable(inputDate).map(Date::getTime).map(Date::new).orElse(null);
}}
参考:Is there a way to copy Date object into another date Object without using a reference?(Nicolas Henneaux的答案)
答案 4 :(得分:1)
用户无法“替换”getCommentDate()提供的实例。但是,用户可以调用getCommentDate()。setMonth(10),从而修改日期。因此,如果这是一个问题,我建议你返回“原始”实例的副本。
答案 5 :(得分:1)
由于java.util.Date
是可变的,因此可以通过getter更改它:
getCommentDate().setYear(2011)
这会导致评论中的commentDate
更改为2011年。Date
上的所有其他设置方法也可以调用,当然只是一个示例。
答案 6 :(得分:0)
在Java中,您正在处理引用。当你有一个getter并返回 commentDate 时,你实际上正在返回对该对象的引用。这意味着,由于getter返回的引用,调用者可以操作的私有字段中的相同对象。
答案 7 :(得分:0)
注意:不要通过getters返回可变对象。日期(在Java 8之前)。流氓程序员始终可以将其重置。假设您编写了一个程序,其中根据工作年限计算员工的社会保障福利。
public class Employee {
// instance fields
private String name;
private String nickName;
private double salary;
private Date hireDay;
// constructor
Employee(String name, String aNickName, double aSalary, int aYear,
int aMonth, int aDay) {
this.name = name;
nickName = aNickName;
salary = aSalary;
GregorianCalendar cal = new GregorianCalendar(aYear, aMonth - 1, aDay);
hireDay = cal.getTime();
}
//needs to be corrected or improved because date is a mutable object
public Date getHireDay() {
return hireDay;
}
黑客/不良程序员可以使用setter重置日期
Employee john = new Employee("John", "Grant", 50000, 1989, 10, 1);
Date d = john.getHireDay();
// Original hire date is Oct 1, 1989
System.out.println("Original hire date "+ d.getTime()));
long tenYearsInMilliseconds = 10 * 365 * 24 * 60 * 60 * 1000L;
long time = d.getTime();
// Hire date after hacker modifies the code
d.setTime(time - tenYearsInMilliseconds);
System.out.println("Hacked hire date "+john.getHireDay().getTime()));
}
相反,..返回Java 7的date方法的克隆或使用Java 8的LocalDate类。
// for Java 7
public Date getHireDay() {
return (Date)hireDay.clone();
}
//for Java 8
public LocalDate getHireDay() {
return hireDay;
}