Java返回可变引用对象问题整理

所属分类: 软件编程 / java 阅读数: 37
收藏 0 赞 0 分享

1.问题

/**
 * 输出: Mon Apr 26 10:54:10 CST 2010
 *    Mon Apr 26 10:54:10 CST 2010
 */
public static void main(String[] args){
  Example test = new Example(new Date());

  Date d = test.getDate();
  double tenYearsInMillisSeconds = 10 * 365.25 * 24 * 3600 * 1000;
  d.setTime((long) (d.getTime() - tenYearsInMillisSeconds));

  System.out.println(d);
  System.out.println(test.getDate());
}

public class Example {
  private Date date;

  public Example(Date date){
    this.date = date;
  }

  public Date getDate() {
    return date;
  }
}

Date类破坏了Example的封装,导致修改实例 d时影响了 test 的值,原因是Date类生成的对象是可变的。

2.对象与对象变量

Date birthday = new Date();
Date deadline = birthday;

这两个变量引用同一个对象(请参见图 4-4 )。

但一个对象变量并没有实际包含一个对象,而仅仅引用一个对象。

在 Java 中,任何对象变量的值都是对存储在另外一个地方的一个对象的引用。new 操作符的返回值也是一个引用。

Date birthday = new Date();可以理解为new Date() 构造了一个 Date 类型的对象, 并且它的值是对新创建对象的引用。这个引用存储在变量 birthday中。

Java 对象变量与 C++ 的引用并不同

可以将 Java 的对象变量看作 C++ 的对象指针。例如,

Date birthday; // Java

实际上,等同于

Date* birthday; // C++

所有的 Java 对象都存储在堆中。 当一个对象包含另一个对象变量时, 这个变量依然

包含着指向另一个堆对象的指针。

3.更改器方法与访问器方法

上文还是没有解释清楚为什么Date类的对象是可变对象,原因在这。

假设在上文中Example类中使用Java中与Date类相近的LocalDate类便不会出现上述情况,测试可以自己去尝试。

原因在于假设使用LocalDate类中的plusDays 方法来修改对象变量,它会生成一个新的LocalDate对象,然后把这个新对象赋值给调用者,原来的对象不做任何改动。

此类只访问对象而不修改对象的方法有时称为访问器方法(accessor method)

而像Date类中的setTime方法会使得原对象的状态发生改变,此类称为更改器方法(mutator method)

4.解决方法

如果需要返回一个可变数据域的拷贝,就应该使用 clone。这样会创建一个当前对象的副本,而不会对当前对象造成影响。

public class Example {
  private Date date;

  public Example(Date date){
    this.date = date;
  }

  public Date getDate() {
	return (Date) date.clone();
  }
}

5.不可变类

5.1什么是不可变类

不可变类指当类被实例化后,该类的成员变量均不可被改变。

如JDK内部自带的很多不可变类IntergerLongBooleanString等。

5.2优缺点 优点:

1.线程安全

2.易于构造、使用和测试

3.可以被自由地共享缺点:对于每一个不同的值都需要对应一个单独的对象 5.3如何实现不可变类 Class需要用final修饰,保证类不能被继承所有成员变量需要private修饰,保证成员变量不能直接被访问类中不允许提供setter方法,保证成员变量不会被改变在getter方法中不能返回对象本身,返回对象的拷贝

更多精彩内容其他人还在看

SpringBoot中使用Ehcache的详细教程

EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvider。这篇文章主要介绍了SpringBoot中使用Ehcache的相关知识,需要的朋友可以参考下
收藏 0 赞 0 分享

在idea 中添加和删除模块Module操作

这篇文章主要介绍了在idea 中添加和删除模块Module操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

java spring整合junit操作(有详细的分析过程)

这篇文章主要介绍了java spring整合junit操作(有详细的分析过程),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

详解JAVA 弱引用

这篇文章主要介绍了 JAVA 弱引用的相关资料,帮助大家更好的理解和学习java引用对象,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

深入了解JAVA 虚引用

这篇文章主要介绍了JAVA 虚引用的相关资料,帮助大家更好的理解和学习JAVA,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

详解JAVA 强引用

这篇文章主要介绍了JAVA 强引用的相关资料,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

java中的按位与(&)用法说明

这篇文章主要介绍了java中的按位与(&)用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

深入了解JAVA 软引用

这篇文章主要介绍了JAVA 软引用的相关资料,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

利用MyBatis实现条件查询的方法汇总

这篇文章主要给大家介绍了关于利用MyBatis实现条件查询的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用MyBatis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

Intellij IDEA 与maven 版本不符 Unable to import maven project See logs for details: No implementation for org.apache.maven.model.path.PathTranslator was bound

这篇文章主要介绍了Intellij IDEA 与maven 版本不符 Unable to import maven project See logs for details: No implementation for org.apache.maven.model.path.Pa
收藏 0 赞 0 分享
查看更多