`
su1216
  • 浏览: 671971 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
Group-logo
深入入门正则表达式(jav...
浏览量:72007
E60283d7-4822-3dfb-9de4-f2377e30189c
android手机的安全问...
浏览量:128914
社区版块
存档分类
最新评论

java中的clone(+标记接口说明)

    博客分类:
  • java
阅读更多

复习一下clone,顺便整理下笔记

clone即复制
你有一个引用为A的对象,我也想要一个一模一样的对象,如果能复制出来一个就好啦
在java里面提供了这种复制的操作--clone
为了笔记的完整性,先给出一个更基础的错误例子

下面是一个普通的Animal类

public class Animal implements Cloneable{
	public String name = "";
	public boolean lovely = true;
	protected ArrayList<String> foodList = new ArrayList<String>();
	protected Personal personal;
	
	static class Personal implements Cloneable{
		public int age = 0;
		
		public Personal clone() throws CloneNotSupportedException{
			return (Personal) super.clone();
		}
	}
	
	public Animal clone() throws CloneNotSupportedException{
		return (Animal) super.clone();
	}

	public List<String> getFoodList(){
		return foodList;
	}
	
	public void addFood(String f){
		foodList.add(f);
	}
}
 

这里有一个Personal的内部静态类,一会再看这个东西,先忽略

 

如果真的有人想复制对象,但是又写成了下面的代码,那么他真应该好好看看基础了

public static void main(String[] args) {
    Animal animal = new Animal();
    animal.lovely = false;
    
    Animal animalCopy = animal;
    animalCopy.lovely = true;
    System.out.println(animal.lovely);
    System.out.println(animalCopy.lovely);
}

 这里Animal animalCopy = animal;只是新建了一个Animal的引用而已
对象呢,还是原先的对象,两个引用指向同一个对象
如果对象改变了,那么animal.lovely和animalCopy.lovely的值也都会改变。因为他们本来就是同一个对象的lovely,当然一起变了,所以结果都是true

如果想clone,我们可以通过clone来实现
clone是Object 的方法,发现这个方法是protected 的,返回类型是Object
如果外面想调用它,那起码要先变成public的,这样还不行,Personal还要实现Cloneable才可以
那我们看看Cloneable里面都是些神马吧

 

public interface Cloneable { 
}

 - -
里面神马也没有,那它有啥作用?
obj instanceof Cloneable
恩,可以这么写,似乎只能作为类型检查 来用了
既然要去Animal必须实现Cloneable这个接口,那么看来clone时候是需要做类型检查的
这种接口在结尾再继续说明

 

try {
    Animal animalCopy = (Animal)animal.clone();
    animalCopy.lovely = true;
    System.out.println(animal.lovely);
    System.out.println(animalCopy.lovely);
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}

这回打印的结果是false和true了

clone貌似很简单,可是很不幸,这只是简单的情形而已

 

这时候看看Personal这个类吧

Personal p = new Personal();
p.age = 1;
animal.personal = p;

 给animal对象一个personal属性,我们看看结果会怎样

 

try {
	Animal animalCopy = (Animal)animal.clone();
	animalCopy.lovely = true;
	System.out.println(animal.lovely);
	System.out.println(animal.personal.age);
	System.out.println(animalCopy.lovely);
	System.out.println(animalCopy.personal.age);
	animalCopy.personal.age = 2;
	System.out.println(animal.lovely);
	System.out.println(animal.personal.age);
	System.out.println(animalCopy.lovely);
	System.out.println(animalCopy.personal.age);
} catch (CloneNotSupportedException e) {
	e.printStackTrace();
}

/////////////////
false
1
true
1
false
2
true
2

lovely和预想的一样,一个true一个false,但是age似乎就有些问题了

我们明明只改动了lovely动物的age,为啥不lovely的动物也跟着涨了一岁!

 

clone分为深clone和浅clone

浅clone只clone对象中的基本类型

深clone随意clone了,想clone就clone什么,可惜java并没为大家实现深clone

 

上面的例子personal没有被clone

那么我们在animal的clone来实现

public Animal clone() throws CloneNotSupportedException{
    Animal a = (Animal) super.clone();
    a.foodList =  (ArrayList<String>)foodList.clone();
    if(personal != null){
        a.personal = personal.clone();
    }
    return a;
}

看出我们的Personal类也需要实现Cloneable接口,重写clone方法

这时候我们再运行之前的代码,结果正确

不lovely的动物age=1,lovely的动物age=2

 

我们还会发现animal的foodList也被clone了(代码省略)

之所以可以这么写foodList.clone();,是因为sun帮我们实现了clone

 

目前我们有了lovely和不lovely的动物,还没有给他们起名字呢,一个叫lion一个叫dog好了

public static void main(String[] args) {
	Animal animal = new Animal();
	animal.name="lion";
	try {
		Animal animalCopy = (Animal)animal.clone();
		animalCopy.name = "dog";
		System.out.println(animal.name);
		System.out.println(animalCopy.name);
	} catch (CloneNotSupportedException e) {
		e.printStackTrace();
	}
}

按着上面讲的,打印结果应该都是dog才对,因为我们并没有对String进行clone

原因是String是不可变对象(immutable)

以String为例,String是用来表示字符串的类,它并没有提供任何改变字符串属性的方法,也就是说:String实例所代表的字符串属性,绝对不会改变(引自java多线程设计模式第二章immutable pattern)

 

有了上面的解释,这里就好理解多了

String是不可变的,那下面这句话就是让animalCopy.name指向一个新的对象了

animalCopy.name = "dog";

两个动物的name指向不同的对象,所以结果也不一样

回头再看animal这个类,如果它只有基本类型的属性和不可变类型的属性,或是是子对象生命周期内不会发生变化也不提供更改其方法的对象,那么只需浅clone就可以了。否则需要深clone

 

-------------------------------------------------------------

标记接口(tagging interface/marker interface)

标识接口是没有任何方法和属性的接口.
它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情.
使用标记接口的唯一目的是使得可以用instanceof进行类型查询

 

 

java.io.Serializable
未实现此接口的类将无法使其任何状态序列化或反序列化.
为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值.

java.lang.Cloneable
表明Object.clone()方法可以合法地对该类实例进行按字段复制.
实现此接口的类应该使用公共方法重写 Object.clone(它是受保护的).
如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException 异常.

java.util.RandomAccess
用来表明其支持快速(通常是固定时间)随机访问.
此接口的主要目的是允许一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能.

java.rmi.Remote                          
Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口.
任何远程对象都必须直接或间接实现此接口.
只有在“远程接口”(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用.

 

 

转贴请保留以下链接

 

本人blog地址

http://su1216.iteye.com/

http://blog.csdn.net/su1216/

 

分享到:
评论

相关推荐

    Java深浅clone

    这个接口没有任何方法定义,只作为一个标记接口使用。当尝试对未实现`Cloneable`接口的对象调用`clone()`方法时,会抛出`CloneNotSupportedException`异常。 浅克隆是指创建一个新对象,它的字段与原始对象的字段...

    Java中clone方法共6页.pdf.zip

    - Java中的`Cloneable`接口是一个标记接口,没有定义任何方法。当一个类实现了`Cloneable`接口,表示该类的对象可以被克隆。如果不实现这个接口,调用`clone()`方法会抛出`CloneNotSupportedException`。 3. **...

    java clone

    1. 实现`Cloneable`接口:这是Java中定义的一个标记接口,没有包含任何方法。当一个类实现了这个接口,表明它允许被克隆。 2. 覆盖`clone`方法:在自定义类中,我们需要重写`clone`方法以实现特定的克隆逻辑。默认的...

    java Clone

    Java中的`clone`方法是Java语言提供的一种复制对象的方式,它允许创建一个对象的副本,这个副本与原对象具有相同的属性值,但它们是两个独立的对象,修改副本不会影响原对象。`clone`方法存在于Java的`java.lang....

    Java的clone方法[归类].pdf

    在`A`类中,我们首先需要实现`Cloneable`接口,这是一个标记接口,表明类支持克隆。然后,我们需要重写`clone()`方法。这里,我们调用`super.clone()`,这是因为`Object`类的`clone()`方法会创建当前对象的一个副本...

    Java Clone(类的复制)实例代码

    在Java中,如果一个类想要实现`clone()`方法,必须实现`Cloneable`接口。如果不这样做,Java会抛出`CloneNotSupportedException`异常。`Cloneable`接口本身没有定义任何方法,它的作用就是标记一个类为可克隆的。 ...

    关于java clone的一些基本的概念

    不过要注意的是,`Cloneable`接口本身没有任何方法,只是一个标记接口。实现这个接口并不自动重写`Object`类的`clone`方法,所以还需要我们自己覆盖`clone`并实现深拷贝或浅拷贝逻辑。 在`clone`方法中,有几点需要...

    Clone详解.doc

    Java中的`Cloneable`接口是一个标记接口,没有定义任何方法。一个类如果想要实现克隆,必须实现这个接口。否则,调用`clone()`方法时会抛出`CloneNotSupportedException`。实现`Cloneable`接口表明类支持克隆操作。...

    JAVA对象clone方法代码实例解析

    首先,我们首先需要了解Cloneable接口,这个接口是一个标记接口,里面没有任何方法,但是它的存在是非常重要的,因为它规定了一个类是否可以被clone。如果一个类没有实现Cloneable接口,那么它就不能被clone,它的...

    JAVA_高级特性(hashCode,clone,比较器,Class反射,序列化)

    在示例中,`Person` 类实现了 `Serializable` 接口,并且 `age` 字段被标记为 `transient`,这意味着在序列化过程中不会保存 `age` 的值。 序列化的实现代码如下: ```java // 序列化 ObjectOutputStream oos = ...

    Thinking in Java 中文第四版+习题答案

    2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...

    10道 基础 Java 面试题

    Java 中多态是通过继承和接口实现的。继承允许子类继承父类的方法和属性,同时可以重写父类的方法,从而实现多态;而接口则允许不同的类通过实现同一个接口来达到多态的效果。在 Java 中,多态性是通过方法重写和...

    clone()方法示例(对象克隆)_对象克隆_nervouse78_源码

    1. **实现Cloneable接口**:`Cloneable`接口在Java中是一个标记接口,表示该类的对象可以被克隆。虽然它没有定义任何方法,但实现这个接口是调用`clone()`的前提。 2. **重写`clone()`方法**:默认的`clone()`方法...

    java 原型模式

    这个接口没有定义任何方法,仅仅是一个标记接口。当一个对象实现了`Cloneable`接口,系统就知道这个对象是可克隆的。然而,仅仅实现`Cloneable`接口还不够,还需要重写`Object`类中的`clone()`方法。默认的`clone()`...

    JAVA_对象克隆

    `Cloneable`接口本身不包含任何方法,只是一个标记接口,表明该类的对象可以被克隆。`Object`类的`clone()`方法会创建一个新的对象,并尽可能地复制原对象的数据。如果一个对象没有实现`Cloneable`接口,调用`clone...

    Java对象的复制克隆

    为了使对象可克隆,子类需要实现 `Cloneable` 接口,这是一个标记接口,不包含任何方法,只是告诉Java虚拟机(JVM)该对象支持克隆。同时,由于 `clone()` 是 `native` 方法,它的执行效率通常高于普通的Java方法。 ...

    编程语言java对象复制.pdf

    在Java中,实现Cloneable接口是一个标记,表示该对象的类支持Object类的clone()方法。Cloneable接口本身不包含任何方法,其存在的目的是为了标识哪些类的对象可以被克隆。需要注意的是,Cloneable接口并不是 Clone()...

Global site tag (gtag.js) - Google Analytics