设为首页 加入收藏

TOP

Java对象克隆(一)
2017-10-16 18:20:35 】 浏览:4633
Tags:Java 对象 克隆

一、前言

前两天,去应聘一家公司的笔试题,里面一道编程题目如下:

请问你如何理解Java中的对象克隆呢?

当时一脸懵逼,虽然秉承着不留空白的原则将那道题目写了一大堆,但是可惜结果是错误的。接下来我会将自己的错误贴在下面。读者别效仿笔者,闹出笑话。然后回来重新回炉了相关的知识,发现一位大神的博客解释的很到位。所以这里很多东西都是对该博主的内容进行转载,并且按照自己的理解加以修改的。

下面附上博主的链接:http://www.cnblogs.com/Qian123/p/5710533.html#_labelTop,毕竟人家也是辛辛苦苦整理的博文,因此在这里表示对该博主的感谢。

二、认识Java对象克隆

java面向对象的编程当中,要复制引用类型的对象,就必须克隆这些对象。通过调用对所有引用类型和对象都是可用的clone方法,来实现克隆。如果是值类型的实例,那么“=”赋值运算符就可以将源对象的状态逐字节地复制到目标对象中。笔者理解:也就是对象克隆的话,那么就是说,我们将目前这个对象复制了一份,而被复制的那个对象其实没有改变,我们要操作的只是克隆得到的那个对象,而不会修改被复制的克隆对象。(PS:解释的有点乱,但笔者自己是能够理解,有更加通俗易懂的说法,请在评论区指教!)

三、关于对象克隆的认知错误

在说克隆对象之前,先来讲讲变量的复制:

int apples = 5;  
int pears = apples;  

以上就是变量的复制,并且不仅仅是int类型的可以复制,其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况。

但是对于对象的复制(克隆)的话,情况就有点复杂了,因为笔者之前也没有接触过,所以导致了认知上的一些错误。下面将自己认知错误贴在下面:

package com.ygh.cloneObj;

/**
 * 学生类
 * 
 * @author 夜孤寒
 * @version 1.1.1
 */
class Student {
    private int number;

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

}

/**
 * 测试类
 * 
 * @author Administrator
 * @version 1.1.1
 */
public class Test {

    public static void main(String args[]) {
        // 创建对象
        Student stu_1 = new Student();
        stu_1.setNumber(12345);
        // 对象引用赋值
        Student stu_2 = stu_1;

        System.out.println("学生1:" + stu_1.getNumber());
        System.out.println("学生2:" + stu_2.getNumber());
    }
}

以上代码的输出结果如下:

可能这时候我们就会以为我们已经达到了克隆的目的了,但是其实不是这样的,我们用事实来讲述我们的错误,我们将stu_2的setNumber()方法设置为54321,贴出源代码:

package com.ygh.cloneObj;

/**
 * 学生类
 * 
 * @author 夜孤寒
 * @version 1.1.1
 */
class Student {
    private int number;

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

}

/**
 * 测试类
 * 
 * @author Administrator
 * @version 1.1.1
 */
public class Test {

    public static void main(String args[]) {
        // 创建对象
        Student stu_1 = new Student();
        stu_1.setNumber(54321);
        // 对象引用赋值
        Student stu_2 = stu_1;

        System.out.println("学生1:" + stu_1.getNumber());
        System.out.println("学生2:" + stu_2.getNumber());
    }
}

输出结果:

这时候我们就会发现两者的结果都是54321。

 这时候我们就会发现,我们仅仅是设置了stu_2的值,但是stu_1的值也跟着改变了。这就是说我们并没有达到对象克隆的目的。下面我们从内存图来理解为什么会出现这种情况:

 

我们会发现我们仅仅是将stu_1的引用赋值给stu_2引用而已,两者指向的其实还是同一个对象,也就是说我们根本没有达到对象克隆的目的。

那么如何能够复制一个对象呢?

我们可以记得Object这个所有类的源头,它有11个方法,有两个protected的方法,其中一个为clone方法。

在Java中所有的类都是缺省的继承自Java语言包中的Object类的,查看它的源码,你可以把你的JDK目录下的src.zip复制到其他地方然后解压,里面就是所有的源码。发现里面有一个访问限定符为protected的方法clone():

/*
Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object.
The general intent is that, for any object x, the expression:
1) x.clone() != x will be true
2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.
3) x.clone().equals(x) will be true, this is not an absolute requirement.
*/
protected native Object clone() throws CloneNotSupportedException;

仔细一看,它还是一个native方法,大家都知道native方法是非Java语言实现的代码,供Java程序调用的,因为Java程序是运行在JVM虚拟机上面的,要想访问到比较底层的与操作系统相关的就没办法了,只能由靠近操作系统的语言来实现。

  1. 第一次声明保证克隆对象将有单独的内存地址分配。
  2. 第二次声明表明,原始和克隆的对象应该具有相同的类类型,但它不是强制性的。
  3. 第三声明表明,原始和克隆的对象应该是平等的equals()方法使用,但它不是强制性的。

因为每个类直接或间接的父类都是O

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇IO (一) 下一篇三、第一个IDEA创建的MAVEN工程—..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目