Java中clone方法使用筆記
注解
定義: 注解是一種注釋機制,它可以注釋包、類、方法、變量、參數(shù),在編譯器生成類文件時,標(biāo)注可以被嵌入到字節(jié)碼中。
注解的分類:
內(nèi)置注解
Override :重寫方法,引用時沒有該方法時會編譯錯誤
public class Animals { public void run(){ System.out.println("動物跑"); } }
public class Cat extends Animals{ @Override public void run1() { super.run(); } }
Deprecated :標(biāo)記過時方法,會造成編譯警告
public class Animals { @Deprecated public void run(){ System.out.println("動物跑"); } }
SuppressWarnings :用于編譯器去忽略注解中的聲明報告
FunctionalInterface :用于指示被修飾的接口是函數(shù)式接口
元注解(修飾注解的注解)
@Retention -標(biāo)記這個注解存儲在哪里
@Documented -標(biāo)記這些注解是否包含在用戶文檔中
@Target -標(biāo)記這些注解時java哪種成員
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ //可以應(yīng)用于類的任何元素 TYPE, //可以用于字段或?qū)傩? /** Field declaration (includes enum constants) */ FIELD, //可以用于方法級注釋 /** Method declaration */ METHOD, //可以用于方法的參數(shù) /** Formal parameter declaration */ PARAMETER, //可以應(yīng)用于構(gòu)造函數(shù) /** Constructor declaration */ CONSTRUCTOR, //可以用于局部變量 /** Local variable declaration */ LOCAL_VARIABLE, /** Annotation type declaration */ ANNOTATION_TYPE, //可以用于包聲明 /** Package declaration */ PACKAGE, /** * Type parameter declaration * * @since 1.8 */ TYPE_PARAMETER, /** * Use of a type * * @since 1.8 */ TYPE_USE }
@Inherited -標(biāo)記這個注解時繼承于哪個類
@Repeatable -標(biāo)識某注解可以在同一個聲明上使用多次
public enum RetentionPolicy { /** * Annotations are to be discarded by the compiler. */ SOURCE,//在源文件中有效(源文件保存) /** * Annotations are to be recorded in the class file by the compiler * but need not be retained by the VM at run time. This is the default * behavior. */ CLASS,//在class文件中有效(class保存) /** * Annotations are to be recorded in the class file by the compiler and * retained by the VM at run time, so they may be read reflectively. * * @see java.lang.reflect.AnnotatedElement */ RUNTIME//在運行時有效(運行時保留) }
自定義注解
注解類:
@Target(ElementType.FIELD)//作用在類的屬性上 @Retention(RetentionPolicy.RUNTIME)//運行時生效 public @interface NotNull { String message() default ""; int length() default 0; String lengthmessage() default ""; }
model類:
public class User { private int num; @NotNull(message="姓名不能為空",length=3,lengthmessage="長度不能小于3") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } }
測試代碼:
public class Test { public static void main(String[] args) throws NoSuchMethodException, SecurityException, Exception { User user=new User(); Field[] fields=user.getClass().getDeclaredFields();//將類中的字段存儲在field數(shù)組中 //對數(shù)組中的字段進行強循環(huán) for(Field filed:fields){ NotNull notNull=filed.getAnnotation(NotNull.class);//獲取注釋類型 if(notNull!=null){ Method method = user.getClass().getMethod("get" + getMethodName(filed.getName()));//獲取方法對象 Object value = method.invoke(user);//調(diào)用類的實例對象 if(value==null){ System.err.println(filed.getName()+notNull.message());//打印輸出相應(yīng)的字段和注釋信息 throw new NullPointerException(notNull.message());//拋出異常信息 } else if(String.valueOf(value).length()< notNull.length()){//判斷字符串長度 System.err.println(filed.getName()+notNull.lengthmessage()); } } } } /** * 把一個字符串的第一個字母大寫 */ private static String getMethodName(String fildeName) throws Exception { byte[] items = fildeName.getBytes(); items[0] = (byte) ((char) items[0] - 'a' + 'A'); return new String(items); } }
對象克隆
原因:new出來的對象屬性都是初始化的值,不能保存當(dāng)前對象“狀態(tài)”,clone解決了這個問題
//這種形式的代碼復(fù)制的是引用,即對象在內(nèi)存中的地址,car1和car2指向同一個對象 Car car1=new Car(); Car car2=car1;
如何實現(xiàn)克隆
克隆分為淺克隆和深克隆,下面就簡單的介紹它們之前的區(qū)別:
- 淺克隆(值類型克隆值,引用類型傳遞地址)
model類:
public class Person implements Cloneable{ int num; String name; Address address; public Person() { } public Person(int num, String name) { this.num = num; this.name = name; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Override protected Person clone() throws CloneNotSupportedException { Person person = (Person)super.clone(); // person.address = (Address)address.clone(); //深度復(fù)制 聯(lián)同person中關(guān)聯(lián)的對象也一同克隆. return person; } @Override public String toString() { return "Person{" + "num=" + num + ", name='" + name + '\'' + ", address=" + address + '}'; } }
引用類:
public class Address { String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Address{" + "address='" + address + '\'' + '}'; } @Override protected Address clone() throws CloneNotSupportedException { return (Address)super.clone(); } }
測試類:
public class Test { public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address(); address.setAddress("漢中"); Person p1 = new Person(100,"jim"); p1.setAddress(address); Person p2 =p1.clone(); p2.setName("tom"); address.setAddress("西安");// System.out.println(p1); } }
淺克隆中引用對象進行的是引用地址傳遞,原引用對象和克隆對象指向同一個引用地址
強克?。ㄖ殿愋涂寺≈?,引用類型克隆一個帶有原數(shù)據(jù)的新的地址)
引用類:
public class Address implements Cloneable{ String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Address{" + "address='" + address + '\'' + '}'; } @Override protected Address clone() throws CloneNotSupportedException { return (Address)super.clone(); } }
model類:
public class Person implements Cloneable{ int num; String name; Address address; public Person() { } public Person(int num, String name) { this.num = num; this.name = name; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Override protected Person clone() throws CloneNotSupportedException { Person person = (Person)super.clone(); person.address = (Address)address.clone(); //深度復(fù)制 聯(lián)同person中關(guān)聯(lián)的對象也一同克隆. return person; } @Override public String toString() { return "Person{" + "num=" + num + ", name='" + name + '\'' + ", address=" + address + '}'; } }
測試:
public class Test { public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address(); address.setAddress("漢中"); Person p1 = new Person(100,"jim"); p1.setAddress(address); Person p2 =p1.clone(); p2.setName("tom"); address.setAddress("西安"); System.out.println(p1); System.out.println(p2); } }
強克隆中的引用類型新創(chuàng)建的地址賦給克隆對象引用類型
我們也可以通過序列化的方式對對象進行克隆,代碼如下:
引用類:
public class Address implements Serializable { String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Address{" + "address='" + address + '\'' + '}'; } }
model類:
public class Person implements Serializable { int num; String name; Address address; public Person() { } public Person(int num, String name) { this.num = num; this.name = name; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } /** * 自定義克隆方法 * @return */ public Person myclone() { Person person = null; try { // 將該對象序列化成流,因為寫在流里的是對象的一個拷貝,而原對象仍然存在于JVM里面。所以利用這個特性可以實現(xiàn)對象的深拷貝 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(this); // 將流序列化成對象 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); person = (Person) ois.readObject(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return person; } @Override public String toString() { return "Person{" + "num=" + num + ", name='" + name + '\'' + ", address=" + address + '}'; } }
測試類:
public class Test { public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address(); address.setAddress("漢中"); Person p1 = new Person(100,"jim"); p1.setAddress(address); Person p2 =p1.myclone(); p2.setName("tom"); address.setAddress("西安"); System.out.println(p1); System.out.println(p2); } }
總結(jié)
到此這篇關(guān)于Java中clone方法使用的文章就介紹到這了,更多相關(guān)Java中clone方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解SpringBoot 創(chuàng)建定時任務(wù)(配合數(shù)據(jù)庫動態(tài)執(zhí)行)
本篇文章主要介紹了SpringBoot 創(chuàng)建定時任務(wù)(配合數(shù)據(jù)庫動態(tài)執(zhí)行),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10Java如何通過反射獲取私有構(gòu)造、私有對象、私有字段、私有方法
這篇文章主要介紹了Java如何通過反射獲取私有構(gòu)造、私有對象、私有字段、私有方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12SpringBoot配置文件中系統(tǒng)環(huán)境變量存在特殊字符的處理方式
這篇文章主要介紹了SpringBoot配置文件中系統(tǒng)環(huán)境變量存在特殊字符的處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02基于指針pointers和引用references的區(qū)別分析
本篇文章介紹了,基于指針pointers和引用references的區(qū)別分析。需要的朋友參考下2013-05-05java實現(xiàn)在復(fù)制文件時使用進度條(java實現(xiàn)進度條)
在對大文件操作時,可能會需要些時間,此時為用戶提供進度條提示是非常常見的一項功能,這樣用戶就可以了解操作文件需要的時間信息。本實例為大家介紹了在復(fù)制大的文件時使用的進度條提示,需要注意的是,只有在讀取文件超過2秒時,才會顯示進度條2014-03-03Spring Boot 2 實戰(zhàn):自定義啟動運行邏輯實例詳解
這篇文章主要介紹了Spring Boot 2 實戰(zhàn):自定義啟動運行邏輯,結(jié)合實例形式詳細分析了Spring Boot 2自定義啟動運行邏輯詳細操作技巧與注意事項,需要的朋友可以參考下2020-05-05