当前位置: 首页 > news >正文

佛山美容网站建设张雷明任河南省委常委

佛山美容网站建设,张雷明任河南省委常委,申报网站,favicon.ico wordpress文章目录 概述创建对象的5种方式1. 通过new关键字2. 通过Class类的newInstance()方法3. 通过Constructor类的newInstance方法4. 利用Clone方法5. 反序列化 Clone方法基本类型和引用类型浅拷贝深拷贝如何实现深拷贝1. 让每个引用类型属性内部都重写clone()方法2. 利用序列化 概述…

文章目录

  • 概述
  • 创建对象的5种方式
    • 1. 通过new关键字
    • 2. 通过Class类的newInstance()方法
    • 3. 通过Constructor类的newInstance方法
    • 4. 利用Clone方法
    • 5. 反序列化
  • Clone方法
  • 基本类型和引用类型
  • 浅拷贝
  • 深拷贝
  • 如何实现深拷贝
    • 1. 让每个引用类型属性内部都重写clone()方法
    • 2. 利用序列化

在这里插入图片描述

概述

关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象。可能日常编码过程中用得不多,但了解深拷贝和浅拷贝的原理,对于Java中的值传递或者引用传递将会有更深的理解。


创建对象的5种方式

1. 通过new关键字

最常用的一种方式,通过new关键字调用类的有参或无参构造方法来创建对象。比如Object obj = newObject()


2. 通过Class类的newInstance()方法

这种默认是调用类的无参构造方法创建对象。比如Artisan p2 =(Artisan)Class. forName("com. ys.artisan.Artisan").newInstance()


3. 通过Constructor类的newInstance方法

和第2种方法类似,都是通过反射来实现的。通过java.lang. relect. Constructor类的newInstance()方法指定某个构造器来创建对象

  Artisan.class.getConstructor()[0].newInstance();

实际上第2种方法利用Class的newInstance()方法创建对 象,其内部调用还是Constructor的newInstance()方法。


4. 利用Clone方法

Clone是Object类中的一个方法,clone克隆顾名思义就是创建一个一模一样的对象出来。通过对象A. clone()方法会创建一个内容和对象A一模一样的对象B

Artisan a1 = new Artisan();
Artisan a2 = a1.clone();

5. 反序列化

序列化是把堆内存中的Java对象数据,通过某种方式把对象存储到磁盘文件中或者传递给其他网络节点(在网络上传输)​。

而反序列化则是把磁盘文件中的对象数据或者把网络节点上的对象数据,恢复成Java对象模型的过程


Clone方法

我们这里介绍Java的深拷贝和浅拷贝,其实现方式正是通过调用Object类的clone()方法来完成

   @IntrinsicCandidateprotected native Object clone() throws CloneNotSupportedException;

这是一个用native关键字修饰的方法,关于native关键字,不理解也没关系,只需要知道用native修饰的方法就是告诉操作系统去实现。

具体过程不需要了解,只需要知道clone方法的作用就是复制对象并产生一个新的对象。那么这个新的对象和原对象是什么关系呢?


基本类型和引用类型

先拉齐一个概念,在Java中基本类型和引用类型的区别。

在Java中数据类型可以分为两大类:基本类型和引用类型。

  • 基本类型也称为值类型,分别是字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double。
  • 引用类型则包括类、接口、数组、枚举等

Java将内存空间分为堆和栈。基本类型直接在栈中存储数值,而引用类型是将引用放在栈中,实际存储的值是放在堆中,通过栈中的引用指向堆中存放的数据。

基本类型和引用类型在JVM存储结构如图

在这里插入图片描述

  • a和b都是基本类型,其值是直接存放在栈中的;
  • 而c和d是String声明的,这是一个引用类型,引用地址是存放在栈中,然后指向堆的内存空间。
  • d = c;这条语句表示将c的引用赋值给d,那么c和d将指向同一块堆内存空间

浅拷贝

浅拷贝会复制对象的基本字段值,但对于对象中的引用类型字段,浅拷贝仅复制引用地址,而不会创建新的对象实例。即拷贝后的对象与原对象共享相同的引用类型数据。

class Person implements Cloneable {String name;int age;Address address;public Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}// 浅拷贝实现,使用Object.clone()@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}class Address {String city;public Address(String city) {this.city = city;}
}

使用

Person person1 = new Person("Alice", 25, new Address("New York"));
Person person2 = (Person) person1.clone();// 修改 person2 的地址
person2.address.city = "Los Angeles";// person1 的 address 也会被改变,因为浅拷贝复制的是引用地址
System.out.println(person1.address.city);  // 输出 "Los Angeles"

调用对象的clone方法,必须要让类实现Cloneable接口,并且重写clone方法

创建一个新对象,然后将当前对象的非静态字段复制到该新对象,如果字段是值类型的,那么对该字段执行复制;如果该字段是引用类型的,则复制引用但不复制引用的对象。因此,原始对象及其副本引用同一个对象。


深拷贝

弄清楚了浅拷贝后,深拷贝就很容易理解了。深拷贝:创建一个新对象,然后将当前对象的非静态字段复制到该新对象,无论该字段是值类型的还是引用类型,都复制独立的一份。当用户修改其中一个对象的任何内容时,都不会影响另一个对象的内容

深拷贝会递归地复制对象中的所有字段,包括引用类型字段所指向的对象。这样拷贝后的对象与原对象完全独立,互不影响。


如何实现深拷贝

深拷贝就是要让原始对象和克隆之后的对象所具有的引用类型属性不是指向同一块堆内存

1. 让每个引用类型属性内部都重写clone()方法

既然引用类型不能实现深拷贝,那么将每个引用类型都拆分为基本类型,分别进行浅拷贝。比如上面的例子,Person类有一个引用类型Address(其实String也是引用类型,但是String类型有点特殊)​,在Address类内部也重写clone方法

class Person implements Cloneable {String name;int age;Address address;public Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}// 深拷贝实现@Overrideprotected Object clone() throws CloneNotSupportedException {Person cloned = (Person) super.clone();cloned.address = new Address(this.address.city);  // 递归复制引用类型字段return cloned;}
}

使用

Person person1 = new Person("Alice", 25, new Address("New York"));
Person person2 = (Person) person1.clone();// 修改 person2 的地址
person2.address.city = "Los Angeles";// person1 的 address 不会改变,因为深拷贝创建了独立的引用
System.out.println(person1.address.city);  // 输出 "New York"

这种做法有个弊端,这里Person类只有一个Address引用类型,而Address类没有,所以这里只重写Address类的clone方法,但是如果Address类也存在一个引用类型,那么也要重写其clone方法,这样有多少个引用类型,就要重写多少次,如果存在很多引用类型,那么代码量显然会很大,所以这种方法不太合适


2. 利用序列化

序列化是将对象写到流中便于传输,而反序列化则是把对象从流中读取出来。这里写到流中的对象则是原始对象的一个拷贝,因为原始对象还存在JVM中,所以可以利用对象的序列化产生克隆对象,然后通过反序列化获取这个对象。

注意每个需要序列化的类都要实现Serializable接口,如果有某个属性不需要序列化,可以将其声明为transient,即将其排除在克隆属性之外

因为序列化产生的是两个完全独立的对象,所有无论嵌套多少个引用类型,序列化都是能实现深拷贝的

首先,确保要进行深拷贝的类和其引用的类都实现了Serializable接口

import java.io.*;// 需要进行深拷贝的类必须实现 Serializable 接口
class Address implements Serializable {private static final long serialVersionUID = 1L;String city;public Address(String city) {this.city = city;}@Overridepublic String toString() {return "Address{" +"city='" + city + '\'' +'}';}
}class Person implements Serializable {private static final long serialVersionUID = 1L;String name;int age;Address address;public Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", address=" + address +'}';}// 深拷贝方法:使用序列化和反序列化public Person deepCopy() {try {// 将对象写入字节流ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);oos.flush();// 从字节流读取对象ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (Person) ois.readObject();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();return null;}}
}public class DeepCopyExample {public static void main(String[] args) {// 创建原始对象Person person1 = new Person("Alice", 25, new Address("New York"));// 进行深拷贝Person person2 = person1.deepCopy();// 修改 person2 的地址if (person2 != null) {person2.address.city = "Los Angeles";person2.name = "Bob";}// 输出原对象和拷贝对象,验证深拷贝System.out.println("Original person1: " + person1);System.out.println("Copied person2: " + person2);}
}

输出结果:

Original person1: Person{name='Alice', age=25, address=Address{city='New York'}}
Copied person2: Person{name='Bob', age=25, address=Address{city='Los Angeles'}}
  • deepCopy()方法通过序列化将对象写入到ByteArrayOutputStream,再通过ObjectInputStream从字节流中读取对象,生成新的实例。
  • 修改person2的引用类型字段(如address.city)不会影响person1,从而验证了深拷贝的效果。

在这里插入图片描述

http://www.mnyf.cn/news/50736.html

相关文章:

  • 福安 网站设计宁波正规seo快速排名公司
  • 济南网站建设山东酷风友情链接有哪些
  • wordpress 保持空格网站关键词百度自然排名优化
  • 服务器做免费空间网站管理录像教程百度助手下载安装
  • 建设网站都要什么关键词挖掘
  • 网站seoapp百度地图关键词优化
  • 网站内页检测seo服务外包报价
  • 建站软件安卓网课培训机构排名前十
  • 分公司可以建设网站seo点击排名器
  • sql网站发布流程上海网站推广服务公司
  • 中国建设社银行招聘网站公司想做个网站怎么办
  • 网站怎么做阿里妈妈转链seo兼职接单平台
  • 企业做网站系统百度指数人群画像哪里查询
  • 企业品牌网站源码最新seo教程
  • 网站访问慢的原因关键词是什么
  • php动态网站开发简介百搜科技
  • 淘客网站建设写软文的平台有哪些
  • 网站浏览器不兼容怎么办公司做网络推广哪个网站好
  • 做视频网站软件线上营销活动主要有哪些
  • 做经销找厂家好的网站中国十大网站排名
  • 做暧暧小视频免费网站it培训班大概需要多少钱
  • 乐清做网站公司哪家好重庆seo网站哪家好
  • 东莞网站外包网络营销师证书怎么考
  • 网站制作 牛商网今日头条热点新闻
  • 合肥网站设计制作网络营销的主要推广方式
  • 可以用足球做的游戏视频网站云南seo网络优化师
  • 电子商务公司招聘网站优化排名易下拉排名
  • 网站源码建设模板关键词优化技巧有哪些
  • 旅游网站这么做长沙百度推广排名
  • 医院网站建设 利法拉网络百度关键词推广怎么收费