Java中深拷貝和淺拷貝的區(qū)別解析
引用拷貝和對象拷貝
(1)引用拷貝:將對象的引用賦值給引用類型的變量
Object obj = new Object(); Object obj1 = obj;
(2)對象拷貝 創(chuàng)建對象的一個副本,其中副本和源對象的引用是兩個不同的地址,而不是把一個引用賦值給一個新的引用類型的變量
class Demo{ public static void main(String[] args) throws CloneNotSupportedException { User user = new User(); User user1 = (User)user.clone(); System.out.println(user); System.out.println(user1); } } class User implements Cloneable { @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
淺拷貝和深拷貝都是對象拷貝
- 淺拷貝:源對象和拷貝對象的存放地址不同,但被復制的源對象的引用類型屬性存放的地址仍然和源對象的引用類型屬性相同,修改引用類型屬性的屬性會影響相互影響。
- 深拷貝:源對象和拷貝對象的存放地址不同,源對象和拷貝對象各自的引用類型存放的地址也和源對象的引用類型屬性不同,修改引用類型屬性的屬性不會相互影響拷貝對象和源對象。
常見的淺拷貝方式
(1)一個引用類型變量直接賦值給另一個變量
(2)BeaUtil.copyProperties()
常見的深拷貝方式
(1)通過構造器或new的方式
(2)重寫繼承至Object方法的clone方法,并實現Cloneable接口 如果在沒有實現Cloneable 接口的實例上調用 Object 的 clone 方法,則會導致拋出 CloneNotSupportedException 異常,實現Cloneable 接口的目的是:為了告知JVM,此對象允許拷貝
public class Main { public static void main(String[] args) throws CloneNotSupportedException { User user = new User(1, "測試"); User user1 = user.clone(); System.out.println(user1); } } class User implements Cloneable{ private Integer id; private String name; //必須重寫此方法 @Override protected User clone() throws CloneNotSupportedException { return (User)super.clone(); } public User(Integer id, String name) { this.id = id; this.name = name; } }
注意: 當通過Cloneable接口實現深拷貝時,拷貝的源對象的屬性如果是引用對象(String類型除外),則該屬性也需要實現Cloneable接口,并覆寫clone方法,否則該屬性是進行的淺拷貝。
深拷貝特殊情況(String類型)
String類型屬性:Clonable拷貝后兩個對象的相同屬性指向了通過字符串,但字符串是不可以修改的,存放在常量池中,當其中1個對象的該屬性指向另個字符串時,另外一個對象的屬性的引用仍指向原字符串。
public class ProtoTypeDemo { public static void main(String[] args) throws CloneNotSupportedException { Person person = new Person(); person.setId(1L); person.setName("test"); User user = new User(); user.setUsername("測試"); person.setUser(user); Person person1 = person.clone(); User user1 = user.clone(); user1.setUsername("cs"); person1.setUser(user1); System.out.println(person1);//Person{id=1, name='test', user=User{username='cs'}} System.out.println(person);//Person{id=1, name='test', user=User{username='測試'}} } } public class Person implements Cloneable { private Long id; private String name; private User user; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", user=" + user + '}'; } } public class User implements Cloneable{ private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public User clone() throws CloneNotSupportedException { return (User) super.clone(); } @Override public String toString() { return "User{" + "username='" + username + '\'' + '}'; } }
(3)序列化的方式:FastJson、Gson等都可以
class Main{ public static void main(String[] args) { User user = new User(1, "測試"); //序列化 String s = JSONObject.toJSONString(user); //反序列化 System.out.println(s); User user1 = JSON.parseObject(s, User.class); System.out.println(user1); } } public class User { private Integer id; private String name; public User(Integer id, String name) { this.id = id; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
到此這篇關于Java中深拷貝和淺拷貝的區(qū)別解析的文章就介紹到這了,更多相關Java深拷貝和淺拷貝內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot整合SSO(single sign on)單點登錄
這篇文章主要介紹了SpringBoot整合SSO(single sign on)單點登錄,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-06-06詳解spring集成mina實現服務端主動推送(包含心跳檢測)
本篇文章主要介紹了詳解spring集成mina實現服務端主動推送(包含心跳檢測),具有一定的參考價值,與興趣的可以了解一下2017-09-09@PathParam和@QueryParam區(qū)別簡析
這篇文章主要介紹了@PathParam和@QueryParam區(qū)別,分享了相關實例代碼,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下2018-01-01