Java中clone方法使用筆記
注解
定義: 注解是一種注釋機(jī)制,它可以注釋包、類、方法、變量、參數(shù),在編譯器生成類文件時(shí),標(biāo)注可以被嵌入到字節(jié)碼中。
注解的分類:
內(nèi)置注解
Override :重寫方法,引用時(shí)沒有該方法時(shí)會(huì)編譯錯(cuò)誤
public class Animals { public void run(){ System.out.println("動(dòng)物跑"); } }
public class Cat extends Animals{ @Override public void run1() { super.run(); } }
Deprecated :標(biāo)記過時(shí)方法,會(huì)造成編譯警告
public class Animals { @Deprecated public void run(){ System.out.println("動(dòng)物跑"); } }
SuppressWarnings :用于編譯器去忽略注解中的聲明報(bào)告
FunctionalInterface :用于指示被修飾的接口是函數(shù)式接口
元注解(修飾注解的注解)
@Retention -標(biāo)記這個(gè)注解存儲(chǔ)在哪里
@Documented -標(biāo)記這些注解是否包含在用戶文檔中
@Target -標(biāo)記這些注解時(shí)java哪種成員
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ //可以應(yīng)用于類的任何元素 TYPE, //可以用于字段或?qū)傩? /** Field declaration (includes enum constants) */ FIELD, //可以用于方法級(jí)注釋 /** 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)記這個(gè)注解時(shí)繼承于哪個(gè)類
@Repeatable -標(biāo)識(shí)某注解可以在同一個(gè)聲明上使用多次
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//在運(yùn)行時(shí)有效(運(yùn)行時(shí)保留) }
自定義注解
注解類:
@Target(ElementType.FIELD)//作用在類的屬性上 @Retention(RetentionPolicy.RUNTIME)//運(yùn)行時(shí)生效 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();//將類中的字段存儲(chǔ)在field數(shù)組中 //對(duì)數(shù)組中的字段進(jìn)行強(qiáng)循環(huán) for(Field filed:fields){ NotNull notNull=filed.getAnnotation(NotNull.class);//獲取注釋類型 if(notNull!=null){ Method method = user.getClass().getMethod("get" + getMethodName(filed.getName()));//獲取方法對(duì)象 Object value = method.invoke(user);//調(diào)用類的實(shí)例對(duì)象 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()); } } } } /** * 把一個(gè)字符串的第一個(gè)字母大寫 */ private static String getMethodName(String fildeName) throws Exception { byte[] items = fildeName.getBytes(); items[0] = (byte) ((char) items[0] - 'a' + 'A'); return new String(items); } }
對(duì)象克隆
原因:new出來的對(duì)象屬性都是初始化的值,不能保存當(dāng)前對(duì)象“狀態(tài)”,clone解決了這個(gè)問題
//這種形式的代碼復(fù)制的是引用,即對(duì)象在內(nèi)存中的地址,car1和car2指向同一個(gè)對(duì)象 Car car1=new Car(); Car car2=car1;
如何實(shí)現(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)的對(duì)象也一同克隆. 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); } }
淺克隆中引用對(duì)象進(jìn)行的是引用地址傳遞,原引用對(duì)象和克隆對(duì)象指向同一個(gè)引用地址
強(qiáng)克隆(值類型克隆值,引用類型克隆一個(gè)帶有原數(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)的對(duì)象也一同克隆. 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); } }
強(qiáng)克隆中的引用類型新創(chuàng)建的地址賦給克隆對(duì)象引用類型
我們也可以通過序列化的方式對(duì)對(duì)象進(jìn)行克隆,代碼如下:
引用類:
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 { // 將該對(duì)象序列化成流,因?yàn)閷懺诹骼锏氖菍?duì)象的一個(gè)拷貝,而原對(duì)象仍然存在于JVM里面。所以利用這個(gè)特性可以實(shí)現(xiàn)對(duì)象的深拷貝 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(this); // 將流序列化成對(duì)象 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)建定時(shí)任務(wù)(配合數(shù)據(jù)庫動(dòng)態(tài)執(zhí)行)
本篇文章主要介紹了SpringBoot 創(chuàng)建定時(shí)任務(wù)(配合數(shù)據(jù)庫動(dòng)態(tài)執(zhí)行),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10Java如何通過反射獲取私有構(gòu)造、私有對(duì)象、私有字段、私有方法
這篇文章主要介紹了Java如何通過反射獲取私有構(gòu)造、私有對(duì)象、私有字段、私有方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12SpringBoot如何進(jìn)行對(duì)象復(fù)制的實(shí)踐
本文主要介紹了SpringBoot 如何進(jìn)行對(duì)象復(fù)制,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09SpringBoot配置文件中系統(tǒng)環(huán)境變量存在特殊字符的處理方式
這篇文章主要介紹了SpringBoot配置文件中系統(tǒng)環(huán)境變量存在特殊字符的處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02基于指針pointers和引用references的區(qū)別分析
本篇文章介紹了,基于指針pointers和引用references的區(qū)別分析。需要的朋友參考下2013-05-05java實(shí)現(xiàn)在復(fù)制文件時(shí)使用進(jìn)度條(java實(shí)現(xiàn)進(jìn)度條)
在對(duì)大文件操作時(shí),可能會(huì)需要些時(shí)間,此時(shí)為用戶提供進(jìn)度條提示是非常常見的一項(xiàng)功能,這樣用戶就可以了解操作文件需要的時(shí)間信息。本實(shí)例為大家介紹了在復(fù)制大的文件時(shí)使用的進(jìn)度條提示,需要注意的是,只有在讀取文件超過2秒時(shí),才會(huì)顯示進(jìn)度條2014-03-03Spring Boot 2 實(shí)戰(zhàn):自定義啟動(dòng)運(yùn)行邏輯實(shí)例詳解
這篇文章主要介紹了Spring Boot 2 實(shí)戰(zhàn):自定義啟動(dòng)運(yùn)行邏輯,結(jié)合實(shí)例形式詳細(xì)分析了Spring Boot 2自定義啟動(dòng)運(yùn)行邏輯詳細(xì)操作技巧與注意事項(xiàng),需要的朋友可以參考下2020-05-05