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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 19:14:36  来源:igfitidea点击:

How to make a class immutable in java with date field in it?

javaimmutability

提问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 withall 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 类?

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 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多

回答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 immutableclass 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:

上面的类是不可变的,因为:

  1. The instance variable of the class is final i.e. we cannot change the value of it after creating an object.
  2. The class is final so we cannot create the subclass.
  3. There is no setter methods i.e. we have no option to change the value of the instance variable.
  1. 类的实例变量是最终的,即我们不能在创建对象后更改它的值。
  2. 类是最终的,所以我们不能创建子类。
  3. 没有 setter 方法,即我们无法更改实例变量的值。

These points makes this class as immutable. In case of Dateattribute, you can use constructor to set your date with every new object and import org.joda.time.DateTimeclass. This is a better version than the java.util.Datebecause 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** 方法,并且不为此方法提供任何功能。