Java clone方法(下)
1.终于调用的是一个JNI方法,即java本地方法,加高速度
2.使用clone方法,分为浅复制、深复制,这里直接使用网上抄来的案例来说明吧:
说明:
1)为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在执行时刻,Object中的clone()识别你要复制的是哪一个对象,然后为此对象分配空间。并进行对象的复制,将原始对象的内容一一拷贝到新对象的存储空间中。
2)继承自java.lang.Object.clone()方法是浅层复制。一下代码能够证明之:
1 public class Student implements Cloneable {
2 private String name;
3 private int age;
4 private Professor pro;
5 public Student(){}
6 public Student(String name,int age,Professor pro){
7 this.name=name;
8 this.age=age;
9 this.pro=pro;
10 }
11 public Object clone(){
12 Object o=null;
13 try {
14 //Object中的clone()识别出你要复制的是哪一个对象。
15 o=super.clone();
16 } catch (CloneNotSupportedException e) {
17 System.out.println(e.toString());
18 }
19 return o;
20 }
21 public String getName() {
22 return name;
23 }
24 public void setName(String name) {
25 this.name = name;
26 }
27 public int getAge() {
28 return age;
29 }
30 public void setAge(int age) {
31 this.age = age;
32 }
33 public Professor getPro() {
34 return pro;
35 }
36 public void setPro(Professor pro) {
37 this.pro = pro;
38 }
39 }
40 class Professor{
41 private String name;
42 private int age;
43 public Professor(){}
44 public Professor(String name,int age){
45 this.name=name;
46 this.age=age;
47 }
48 public String getName() {
49 return name;
50 }
51 public void setName(String name) {
52 this.name = name;
53 }
54 public int getAge() {
55 return age;
56 }
57 public void setAge(int age) {
58 this.age = age;
59 }
60 }
1 public class StudentTest {
2 public static void main(String[] args) {
3 Professor p=new Professor("wangwu",50);
4 Student s1=new Student("zhangsan",18,p);
5 Student s2=(Student)s1.clone();
6 s2.getPro().setName("maer");
7 s2.getPro().setAge(40);
8 System.out.println("name="+s1.getPro().getName()
9 +",age="+s1.getPro().getAge());
10 //name=maer,age=40
11 }
12 }
那么我们怎样实现深层复制的克隆,即在改动s2.Professor时不影响s1.Professor?代码改进例如以下:
1 public class Student implements Cloneable {
2 private String name;
3 private int age;
4 Professor pro;
5 public Student(){}
6 public Student(String name,int age,Professor pro){
7 this.name=name;
8 this.age=age;
9 this.pro=pro;
10 }
11 public Object clone(){
12 Student o=null;
13 try {
14 //Object中的clone()识别出你要复制的是哪一个对象。
15 o=(Student)super.clone();
16 } catch (CloneNotSupportedException e) {
17 System.out.println(e.toString());
18 }
19 o.pro=(Professor)pro.clone();
20 return o;
21 }
22 public String getName() {
23 return name;
24 }
25 public void setName(String name) {
26 this.name = name;
27 }
28 public int getAge() {
29 return age;
30 }
31 public void setAge(int age) {
32 this.age = age;
33 }
34 public Professor getPro() {
35 return pro;
36 }
37 public void setPro(Professor pro) {
38 this.pro = pro;
39 }
40 }
41 class Professor implements Cloneable{
42 private String name;
43 private int age;
44 public Professor(){}
45 public Professor(String name,int age){
46 this.name=name;
47 this.age=age;
48 }
49 public Object clone(){
50 Object o=null;
51 try {
52 o=super.clone();
53 } catch (CloneNotSupportedException e) {
54 e.printStackTrace();
55 }
56 return o;
57 }
58 public String getName() {
59 return name;
60 }
61 public void setName(String name) {
62 this.name = name;
63 }
64 public int getAge() {
65 return age;
66 }
67 public void setAge(int age) {
68 this.age = age;
69 }
70 }
public class StudentTest {
public static void main(String[] args) {
Professor p=new Professor("wangwu",50);
Student s1=new Student("zhangsan",18,p);
Student s2=(Student)s1.clone();
s2.getPro().setName("maer");
s2.getPro().setAge(40);
System.out.println("name="+s1.getPro().getName()
+",age="+s1.getPro().getAge());
//name=wangwu,age=50
}
}
也就是说浅复制仅仅复制了一些主要的属性,可是里面的引用的属性并没有真正的复制,所以假设想要达到深复制,还要在复写的代码中进行处理。将全部引用的对象也都调用它们的clone()方法。
下面是摘抄的网友的三点小总结:
clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
①对不论什么的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
②对不论什么的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
③假设对象x的equals()方法定义恰当。那么x.clone().equals(x)应该成立。
以下重点说一下,为什么String相同是对象。可是却不用特殊处理;理由例如以下:
String不是基本数据类型。可是在深复制的时候并没有进行单独的复制。也就是说违反了深复制,只复制了引用,而String没有实现cloneable接口,也就是说只能复制引用。
那么在改动克隆之后的对象之后,会不会将原来的值也改变了?
答案肯定是不会改变,由于String是在内存中不能够被改变的对象,就比方说在for大量循环中不推荐使用+的方式来拼凑字符串一样,每次使用+都会新分配一块内存,不在原来上改动,原来的没有指向它的引用,会被回收。所以克隆相当于1个String内存空间有两个引用,当改动当中的一个值的时候。会新分配一块内存用来保存新的值,这个引用指向新的内存空间,原来的String由于还存在指向他的引用,所以不会被回收,这样,尽管是复制的引用,可是改动值的时候,并没有改变被复制对象的值。
所以在非常多情况下。我们能够把String在clone的时候和基本类型做同样的处理。仅仅是在equal时注意一些即可了。
Java clone方法(下)的更多相关文章
- Java clone() 方法克隆对象——深拷贝与浅拷贝
基本数据类型引用数据类型特点 1.基本数据类型的特点:直接存储在栈(stack)中的数据 2.引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里 引用数据类型在栈中存储了指针,该指 ...
- Java clone方法的使用
浅克隆 Person p2 = (Person) p1.clone(); clone()方法使用后得到p2,p2和p1指向不同的地址.但是如果p1中的属性是引用类型,那么不再对这个引用类型进行复制,而 ...
- 详解Java中的clone方法:原型模式
转:http://developer.51cto.com/art/201506/478985.htm clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的 ...
- Effective Java 第三版——13. 谨慎地重写 clone 方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Java 的 clone 方法 && 浅复制和深复制
1 Java中对象的创建过程 java创建对象的方式有以下两种: (1)使用new操作符创建一个对象 (2)使用clone的方法复制一个对象,(在Java中,clone是Object类的protect ...
- java Object对象的clone方法
参考copy链接:http://blog.csdn.net/bigconvience/article/details/25025561 在看原型模式,发现要用到clone这个方法,以前和朋友聊过,没怎 ...
- 详解Java中的clone方法 -- 原型模式
转自: http://blog.csdn.net/zhangjg_blog/article/details/18369201 Java中对象的创建 clone顾名思义就是复制, 在Java语言中, ...
- java中的clone方法
Java中对象的创建 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那 ...
- 深入浅出| java中的clone方法
每天进步一丢丢,连接梦与想 我们还年轻,但这不是你浪费青春的理由 克隆和复制 clone,有人称之为克隆,有人称之为复制,其实都是同一个东西 本文称之为"克隆",毕竟人家方法名叫& ...
随机推荐
- 教你如何清除 MyEclipse/Eclipse 中 Web Browser 和 Switch Workspace 的历史记录
有些许强迫症的开发人员可能会因为 MyEclipse/Eclipse 中 Web Browser 和 Switch Workspace 冗余的历史记录而感到苦恼,下面的方法就可以有效的帮助解决你的痛点 ...
- Gitlab-通过API管理项目
Gitlab有一个非常强大的API,几乎可以通过API管理在Gitlab服务器中的所有项目. 在这里我们只是测试终端点的API, 因此我们需要一个程序来进行测试 .在这里我使用的是针对Google浏览 ...
- linux中shell,awk,sed截取字符串方法总结
转自:http://www.cnblogs.com/kinga/p/5772566.html Shell 第一种: ${parameter%word} 最小限度从后面截掉word${parameter ...
- 8-7 Unique Snowflakes UVA11572
输入一个长度为n n<=10 6 的序列A 找到一个尽量长的连续子序列 使得该序列中没有相同的元素 用滑动窗口法 时间复杂度n 好神奇 此题非常经典 map 410ms #inc ...
- 12:输出1到n位最大整数
如果按照最简单的循环输出,会遇到边界问题,n非常大的话,int甚至long都不能满足需求,所以这里需要用数组或者是字符串来表示要输出的数字. 如果面试题给定了一个n位整数,那么就是大数问题,用字符串来 ...
- thinkphp3.2链接数据库常用的配置选项
thinkphp3.2常用配置选项,app/Common/Conf/config.php 或者 app/Home/Conf/config.php 1 2 3 4 5 6 7 8 'SHOW_PAGE_ ...
- 镣铐之舞:美团安全工程师Black Hat USA演讲
背景 2018年8月9日,全球顶级安全会议——Black Hat USA在美国拉斯维加斯的曼德勒海湾会议中心落下了帷幕,这场盛会在全球黑客心中几乎等同于“世界杯”和“奥斯卡”一样的存在.这场一年一度的 ...
- AlertDialog对话框
普通对话框 public void click1(View v) { //这里不能用 getApplicationContext()方法来获取上下文 AlertDialog.Builder build ...
- MySQL Hash索引和B-Tree索引的区别
MySQL Hash索引和B-Tree索引的区别究竟在哪里呢?相信很多人都有这样的疑问,下文对两者的区别进行了详细的分析,供您参考. MySQL Hash索引结构的特殊性,其检索效率非常高,索引的检索 ...
- python opencv3 直线检测
git:https://github.com/linyi0604/Computer-Vision # coding:utf8 import cv2 import numpy as np # 读入图像 ...