Java 返回可变对象的好方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6503157/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 06:25:28  来源:igfitidea点击:

the good way of returning a mutable object

java

提问by spauny

Let's say I have a class Comment and I have a private field named commentDatewhich is a java.util.Date and with a getter named getCommentDate.

假设我有一个 Comment 类,我有一个名为commentDate的私有字段,它是一个 java.util.Date 和一个名为getCommentDate的getter 。

Why it's better to return a copy of that date ( return new Date(commentDate.getTime())) than simply returning that date...

为什么返回该日期的副本(return new Date(commentDate.getTime()))比简单地返回该日期更好......

How can a user change the object state of that Date since it's a getter, not a setter?

用户如何更改该 Date 的对象状态,因为它是一个 getter,而不是一个 setter?

采纳答案by Karl Knechtel

First off, please, please, pleaseavoid using getters and setters as much as possible. If you have both of them for the same field you are almost certainly doing something wrong. I don't care what the Java gurus are telling you. They don't know what they're talking about. This is not how OO works. OO is not a make-work project to turn field accesses into method calls. That doesn't actually encapsulate anything.

首先,拜托,拜托,尽量避免使用 getter 和 setter。如果你在同一个领域同时拥有它们,你几乎肯定做错了什么。我不在乎 Java 大师告诉你什么。他们不知道他们在说什么。这不是面向对象的工作方式。OO 不是将字段访问转换为方法调用的临时项目。这实际上并没有封装任何东西。

That said: if you return the date itself, then the calling code has a reference to your date object, and can use its full interface. Since dates are mutable objects, the interface includes things that can change the object state. Since the reference is to your date, your date's state will get changed. It doesn't matter how the calling code got the date (i.e. "with a getter").

也就是说:如果您返回日期本身,则调用代码会引用您的日期对象,并且可以使用其完整接口。由于日期是可变对象,因此接口包含可以更改对象状态的内容。由于引用的是您的日期,因此您的日期状态将发生变化。调用代码如何获取日期并不重要(即“使用 getter”)。

回答by Tadeusz Kopec

How can a user change the object state of that Date since it's a getter, not a setter?

用户如何更改该 Date 的对象状态,因为它是一个 getter,而不是一个 setter?

Easily:

容易地:

Comment comment = new Comment();
comment.getCommentDate().setTime(0); // now it's January 1, 1970 00:00:00 GMT.

回答by sbrattla

The user can't "replace" the instance provided by getCommentDate(). However, the user can invoke getCommentDate().setMonth(10) and thereby modifying the date. Thus, if this is a concern, I'd advise you to return a copy of the "original" instance.

用户无法“替换”由 getCommentDate() 提供的实例。但是,用户可以调用 getCommentDate().setMonth(10) 从而修改日期。因此,如果这是一个问题,我建议您返回“原始”实例的副本。

回答by wjans

Since java.util.Dateis mutable, it could be changed via the getter like this:

由于java.util.Date是可变的,因此可以通过 getter 进行更改,如下所示:

getCommentDate().setYear(2011)

This will cause the commentDateon the comment to be changed to the year 2011. All other set methods on Datecan be called as well off course, just an example.

这将导致commentDate注释上的on 更改为 2011 年。Date当然也可以调用所有其他 set 方法,仅举一个例子。

回答by Fabian Barney

In Java you are dealing with references. When you've a getter and returning your commentDatethen you're in fact returning a reference to the object. That means that it is the sameobject like in your private field the caller can operate on due to reference returned by getter.

在 Java 中,您正在处理引用。当您有一个 getter 并返回您的commentDate 时,您实际上是在返回对该对象的引用。这意味着它您的私有字段中的对象相同,由于getter 返回的引用,调用者可以对其进行操作。

回答by Tapas Bose

Since java.util.Dateimplements Cloneableyou can easily clone the date, as:

由于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();
    }       
}

回答by Khanh Tran

Follow Tapas Bose example, we can do the following using JAVA 8 to handle NULL cases:

按照 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);
}}

Reference: Is there a way to copy Date object into another date Object without using a reference?(Nicolas Henneaux's answer)

参考:有没有办法在不使用参考的情况下将日期对象复制到另一个日期对象中?(Nicolas Henneaux 的回答)

回答by karto

Note: Do not return mutable objects via getters eg. date (before Java 8). It can always be reset by a rogue programmer. Lets say you write a program where social security benefits of an employee is calculated based on the years of work.

注意:不要通过 getter 例如返回可变对象。日期(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;
}

A hacker/bad programmer can reset the date using a setter

黑客/坏程序员可以使用 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()));
}

Instead..return a clone of the date method for Java 7 or use LocalDate Class for Java 8

相反......返回 Java 7 的 date 方法的克隆或使用 Java 8 的 LocalDate 类

 // for Java 7
public Date getHireDay() {
    return (Date)hireDay.clone();
}

//for Java 8
public LocalDate getHireDay() {
    return hireDay;
}