zoukankan      html  css  js  c++  java
  • Java 返回可变引用对象的相关问题

    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。这样会创建一个当前对象的副本,而不会对当前对象造成影响。
    有关 clone 的进一步讲解 Java 浅拷贝和深拷贝

    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如何实现不可变类

    1. Class需要用final修饰,保证类不能被继承
    2. 所有成员变量需要private修饰,保证成员变量不能直接被访问
    3. 类中不允许提供setter方法,保证成员变量不会被改变
    4. getter方法中不能返回对象本身,返回对象的拷贝
  • 相关阅读:
    [问题2014A05] 复旦高等代数 I(14级)每周一题(第七教学周)
    oracle的相关信息
    进程和线程的区别
    阿里云人脸检测定位
    php与oracle11g经典分页
    Linux 远程复制
    redis的相关信息
    教你编译PHP7 (nginx+mysql+php7)
    nginx的相关信息
    php about session store db or cache
  • 原文地址:https://www.cnblogs.com/huaranmeng/p/12776250.html
Copyright © 2011-2022 走看看