文档章节

对于所有对象都通用的方法(equals、hashCode、clone)

taole
 taole
发布于 2017/04/06 09:34
字数 1392
阅读 34
收藏 0

1.Object中的clone()方法

protected native Object clone() throws CloneNotSupportedException(以下源引JavaTM 2 Platform Standard Ed. 5.0 API DOC)

创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。一般来说,对于任何对象 x,如果表达式: 

x.clone() != x是正确的,则表达式: x.clone().getClass() == x.getClass()将为 true,但这些不是绝对条件。

一般情况下是: x.clone().equals(x)将为 true,但这不是绝对条件。 

按照惯例,返回的对象应该通过调用 super.clone  获得。如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()。 

按照惯例,此方法返回的对象应该独立于该对象(正被克隆的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被克隆对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。 

Object 类的 clone 方法执行特定的克隆操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。注意:所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我克隆。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。 

Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常 。

编程过程中我们常常遇到如下情况: 假设有一个对象object,在某处又需要一个跟object一样的实例object2,强调的是object和object2是两个独立的实例,只是在开始的时候,他们是具有相同状态的(属性字段的值都相同),跟同卵双胞胎很相似。遇到这种情况的做法一般是,重新new一个对象object2,将object的字段值赋予object2,可以说这种方法很土,我们可以使用clone方法克隆出一个跟object一样的object2,很高效。

误区:有人认为直接将对象object的引用赋予object2就解决问题了,即:object2=object; 这样的话两个引用仍然指向的是同一个对象,不是两个对象。

java.lang.Cloneable 接口(以下源引JavaTM 2 Platform Standard Ed. 5.0 API DOC)

此类实现了 Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。 如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException异常。 

按照惯例,实现此接口的类应该使用公共方法重写 Object.clone(它是受保护的)。请参阅 Object.clone(),以获得有关重写此方法的详细信息。 

注意,此接口不包含 clone 方法。因此,因为某个对象实现了此接口就克隆它是不可能的。即使 clone 方法是反射性调用的,也无法保证它将获得成功。

重写代码如下:

package com.tee.effct.code.example.clone;

/**
 * Created by tll on 2017/4/6.
 */
public class CloneExample1 implements  Cloneable{
    public int a;
    public Object clone(){
        CloneExample1 c=null;
        try {
            c=(CloneExample1) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return  c;
    }
}

上文提到克隆是按属性字段复制的,如果对象的属性值为可变的引用(不可变:如基本类型,final类型的,可变:如对象的引用,数组引用),那原对象跟克隆后的对象将无法保持独立,因为他们的某个属性共同引用了一个对象,这就是“浅表复制”,这不是我们想要的,正常我们需要的是“深层复制 ”,即对对象的属性进行进一步的clone,如下

package com.tee.effct.code.example.clone;

/**
 * Created by tll on 2017/4/6.
 */
public class CloneExample2 implements Cloneable {
    public  String a[];
    public  CloneExample2(){
        a=new String[2];
    }
    public  Object clone(){
        CloneExample2 c2=null;
        try {
            c2=(CloneExample2)super.clone();
            c2.a=(String[]) a.clone();//属性a的克隆,实现A类的深度克隆
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    return  c2;
    }
    /**
     * 如果把public String a[];改为public B a[],如果我们想要得到彻底的拷贝,需要类B也要实现Cloneable接口,
     * 特别在遇到复杂类型时,比如Vector等,
     * 要注意容器中的对象,至于您是否需要深度复制以及复制多少层,都是根据具体需要来定的。
     */
}

其他知识:

this和super用法 

this关键字代表对象自身,在程序中主要的使用用途有以下几个方面:

l  使用this关键字引用成员变量

l  使用this关键字在自身构造方法内部引用其它构造方法

l  使用this关键字代表自身类的对象

l  使用this关键字引用成员方法

super关键字,使用super关键字可以在子类中引用父类中的内容。主要的使用形式有以下几种:

l  在子类的构造方法内部引用父类的构造方法

l  在子类中调用父类中的成员方法

l  在子类中调用父类中的成员变量

 

© 著作权归作者所有

共有 人打赏支持
taole
粉丝 39
博文 48
码字总数 25827
作品 0
杭州
程序员
私信 提问
Java知识点系列:java.lang.Object

Object类位于java.lang包中,java.lang包包含着Java最基础和核心的类,在编译时会自动导入。Object类没有定义属性,一共有13个方法,具体的类定义结构如下图: 1.类构造器public Object(); ...

西皇小明
2016/07/23
21
0
Effective Java-1

1. 考虑使用静态工厂方法代替构造器 类可以使用静态工厂方法来提供它的客户端,而不是构造方法。 静态工厂方法与工厂方法模式不同(工厂方法类根据type生成不同的对象。 提供静态工厂方法而不...

24K男
2017/11/09
0
0
《Effective Java读书笔记》--对于所有对象都通用的方法

equals 如果确定一个函数不会被调用,请在函数中直接 throws UnsupportException,防止程序逻辑出错时还默默执行。 在改写类的equals方法时,要实现如下的等价关系: 自反性 传递性 对称性 ...

7分04秒
2014/05/02
0
0
说说java.lang.Object

Java作为一个庞大的知识体系,涉及到的知识点繁多,本文将从Java中最基本的类java.lang.Object开始谈起。 Object类是Java中其他所有类的祖先,没有Object类Java面向对象无从谈起。作为其他所...

ddddd8
2017/12/02
0
0
Java基础-----基类Object源码分析

在Java中,所有的类都默认继承同一个类,那就是Object类;Object类是唯一没有父类的类;位于java.lang 包下; 1、定义 2、构造器 默认有系统生成无参构造器 public Object(){}; 3、属性 Obje...

baibuxiha
2016/03/14
82
0

没有更多内容

加载失败,请刷新页面

加载更多

第11章 多线程

程序、进程、线程 程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。 **进程(process)**是程序的一次执行过程或是正在运行的一个程序。动...

流小文
42分钟前
4
0
SpringBoot引入第三方jar包或本地jar包的处理方式

在开发过程中有时会用到maven仓库里没有的jar包或者本地的jar包,这时没办法通过pom直接引入,那么该怎么解决呢 一般有两种方法 - 第一种是将本地jar包安装在本地maven库 - 第二种是将本地j...

独钓渔
今天
2
0
五、MyBatis缓存

一、MyBatis缓存介绍 缓存的使用可以明显的加快访问数据速度,提升程序处理性能,生活和工作中,使用缓存的地方很多。在开发过程中,从前端-->后端-->数据库等都涉及到缓存。MyBatis作为数据...

yangjianzhou
今天
2
0
最近研究如何加速UI界面开发,有点感觉了

最近在开发JFinal学院的JBolt开发平台,后端没啥说的,做各种极简使用的封装,开发者上手直接使用。 JBolt开发平台包含常用的用户、角色、权限、字典、全局配置、缓存、增删改查完整模块、电...

山东-小木
今天
3
0
《月亮与六便士》的读后感作文3000字

《月亮与六便士》的读后感作文3000字: 看完英国作家威廉.萨默塞特.毛姆所著《月亮与六便士》(李继宏译),第一疑问就是全书即没提到“月亮”,也没提到“六便士”。那这书名又与内容有什么...

原创小博客
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部