調用一個有參函數的時候,會把實際參數傳遞給形式參數。可是,在程序語言中,這個傳遞過程當中傳遞的兩種狀況,即值傳遞和引用傳遞java
java中只存在值傳遞,不存在引用傳遞apache
對於基本數據類型ide
public class ParamTest { public static void main(String[] args) { ParamTest pt = new ParamTest(); int i = 10; pt.pass(i); System.out.println("print in main , i is " + i); } public void pass(int j) { j = 20; System.out.println("print in pass , j is " + j); } } /* 輸出 print in pass , j is 20 print in main , i is 10 */
因而可知,對於基本數據類型,是在棧中從新創建一個引用 j,使其值等於傳遞的參數值 i,改變 j 並不影響 i函數
對於引用數據類型工具
示例一this
public static void main(String[] args) { ParamTest pt = new ParamTest(); User hello = new User(); hello.setName("Hello"); hello.setGender("Male"); pt.pass(hello); System.out.println("print in main , user is " + hello); } public void pass(User user) { user.setName("HelloChange"); System.out.println("print in pass , user is " + user); } /* 輸出 print in pass , user is User{name='HelloChange', gender='Male'} print in main , user is User{name='HelloChange', gender='Male'} */
示例二code
public static void main(String[] args) { ParamTest pt = new ParamTest(); User hello = new User(); hello.setName("Hello"); hello.setGender("Male"); pt.pass(hello); System.out.println("print in main , user is " + hello); } public void pass(User user) { user = new User(); user.setName("HelloChange"); user.setGender("Male"); System.out.println("print in pass , user is " + user); } /* 輸出 print in pass , user is User{name='HelloChange', gender='Male'} print in main , user is User{name='Hello', gender='Male'} */
示例一中,調用 User 類方法改變了內存地址上對象的屬性,但這並非對傳入參數自己的改變,實際上傳入 hello 以後,在棧中創建 user 引用,且指向地址與 hello 相同,即指向同一對象,對對象的改變並非對 hello 這個引用的改變,其值一直在棧中指向對象空間地址對象
示例二中,傳入 hello 以後,在棧中創建 user 引用並於 hello 等值,但經過 new 對象,使 user 引用指向了新的對象,即 user 在棧中的值改變了,而 hello 的值一直指向原對象並不受影響接口
有時侯咱們須要得到一個新對象,和已經存在的對象徹底相同,但又必須相互獨立,若是使用簡單的賦值方式,實際上指向的仍是同一內存地址上的對象,操做一個引用可能會影響另外一個,這就須要對象拷貝來獲取一個徹底相同的新對象內存
setter/getter
new 新對象後用 set/get 方法設置屬性
淺克隆
class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } class Student implements Cloneable { private int number; private Address addr; public Address getAddr() { return addr; } public void setAddr(Address addr) { this.addr = addr; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } @Override public Object clone() { Student stu = null; try { stu = (Student) super.clone(); //淺複製 } catch (CloneNotSupportedException e) { e.printStackTrace(); } return stu; } } public class Test { public static void main(String args[]) { Address addr = new Address(); addr.setAddress("杭州市"); Student stu1 = new Student(); stu1.setNumber(123); stu1.setAddr(addr); Student stu2 = (Student) stu1.clone(); System.out.println("學生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAddress()); System.out.println("學生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAddress()); stu2.setNumber(124); addr.setAddress("西湖區"); System.out.println("學生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAddress()); System.out.println("學生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAddress()); } } /* 輸出 學生1:123,地址:杭州市 學生2:123,地址:杭州市 學生1:123,地址:西湖區 學生2:124,地址:西湖區 */
經過淺克隆得到新對象,其基本數據類型成員變量獲得了複製,修改後不影響原對象
若變量爲引用數據類型,則只複製地址引用,仍是指向相同地址,修改時會相互影響
若變量爲 String 類型,則拷貝其地址引用。可是在修改時,它會從字符串池中從新生成一個新的字符串,原有字符串對象保持不變
深克隆
class Address implements Cloneable { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public Object clone()//Address 類可複製化 { Address addr = null; try { addr = (Address) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return addr; } } class Student implements Cloneable { private int number; private Address addr; public Address getAddr() { return addr; } public void setAddr(Address addr) { this.addr = addr; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } @Override public Object clone() { Student stu = null; try { stu = (Student) super.clone(); //淺複製 } catch (CloneNotSupportedException e) { e.printStackTrace(); } stu.addr = (Address) addr.clone(); //引用數據類型變量深複製 return stu; } } public class Test { public static void main(String args[]) { Address addr = new Address(); addr.setAddress("杭州市"); Student stu1 = new Student(); stu1.setNumber(123); stu1.setAddr(addr); Student stu2 = (Student) stu1.clone(); System.out.println("學生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAddress()); System.out.println("學生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAddress()); stu2.setNumber(124); addr.setAddress("西湖區"); System.out.println("學生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAddress()); System.out.println("學生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAddress()); } } /* 輸出 學生1:123,地址:杭州市 學生2:123,地址:杭州市 學生1:123,地址:西湖區 學生2:124,地址:杭州市 */
工具類
org.apache.commons 組件 BeanUtils 和 PropertyUtils,靜態方法 copyProperties(Object o1,Object o2)
序列化
序列化就是將對象寫到流的過程,寫到流中的對象是原有對象的一個拷貝,而原對象仍然存在於內存中。經過序列化實現的拷貝不只能夠複製對象自己,並且能夠複製其引用的成員對象,所以經過序列化將對象寫到一個流中,再從流裏將其讀出來,能夠實現深克隆。須要注意的是可以實現序列化的對象其類必須實現Serializable接口,不然沒法實現序列化操做
class Professor implements Serializable { String name; int age; Professor(String name, int age) { this.name = name; this.age = age; } } class Student implements Serializable { String name;//常量對象 int age; Professor p;//引用數據類型 Student(String name, int age, Professor p) { this.name = name; this.age = age; this.p = p; } //深克隆 public Object deepClone() throws IOException, ClassNotFoundException { //將對象寫到流裏 ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject(this); //從流裏讀出來 ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi = new ObjectInputStream(bi); return (oi.readObject()); } } public class Test { public static void main(String[] args) throws IOException, ClassNotFoundException { Professor p = new Professor("wangwu", 50); Student s1 = new Student("zhangsan", 18, p); Student s2 = (Student) s1.deepClone(); s2.p.name = "lisi"; s2.p.age = 30; System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); //學生1的教授不改變 } }