class Address{
    public Address(){
 
    }
 
    public Address(String state, int number){
        this.number = number;
        this.state = state;
    }
 
    @Override
    public String toString(){
        return "state: " + state + " munber: " + number;
    }
 
    public String getState(){
        return state;
    }
 
    public void setState(String state){
        this.state = state;
    }
 
    public int getNumber(){
        return number;
    }
 
    public void setNumber(int number){
        this.number = number;
    }
 
    private String state;
    private int number;
}

public class Employee implements Cloneable{
    public Employee(){
 
    }
 
    public Employee(String name, int age, Address address){
        this.address = address;
        this.age = age;
        this.name = name;
    }
 
    public String getName(){
        return name;
    }
 
    public void setName(String name){
        this.name = name;
    }
 
    public int getAge(){
        return age;
    }
 
    public void setAge(int age){
        this.age = age;
    }
 
    public Address getAddress(){
        return address;
    }
 
    public void setAddress(Address address){
        this.address = address;
    }
 
    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("name:" + name + ", ");
        sb.append("age:" + age + " \n");
        sb.append("Address: " + address);
        return sb.toString();
    }
 
    @Override
    protected Employee clone(){
        Employee employee = null;
        try{
            employee = (Employee) super.clone();
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
        }
        return employee;
    }     private String name;
    private int age;
    private Address address;
    
    
    public static void main(String[] args){
    
        System.out.println("克隆之前:");
        Address add1 = new Address("中国", 1);
        Employee emp1 = new Employee("rollen", 20, add1);
        System.out.println(emp1);
        System.out.println("克隆之后");
        Employee emp2 = emp1.clone();
        System.out.println("====重新设置对象emp2值=====");
        emp2.setName("hello world");
        emp2.setAge(100);
        //emp2.address.setNumber(2);//
        //emp2.address.setState("美国");//原始类的赋值方法
        
        emp2.setAddress(new Address("美国", 2));//本类中的set方法####
        
        System.out.println(emp1);
        System.out.println("-----");
        System.out.println(emp2);
    }
 }
在博客园看到一篇文章,顺手就做了个测试,发现一个问题,就是一个类用用另外一个类的对象作为成员变量时,用来的原始类的set方法给每个变量赋值是可以,但是要用在该类中直接用本类的set方法对对象进行赋值,就是不能赋值成功,我debug了一下,看到值的变化后很奇怪(在####处执行setAddress()方法时,也能看到会把new对象的新值带过去,但是一跳到main函数就是不能带回来),有那位大神解释一下。

解决方案 »

  1.   

    不太清楚你预期的程序结果是什么,你这里的clone方法返回的是一个全部新的Employee对象实例,emp2持有这个新对象实例的引用,这个全新也包括成员变量Address,在你这里克隆对象和原理对象不会引用一个Address,也就是说emp2的任何改动对不会影响emp1的值,而你的程序输出了3次,
    第一次第二次 都是输出的emp1对象,只是克隆前和克隆后,你程序没有修改emp1的值,自然是一样的。
    而emp2你主动改了属性,所以都改了,一切都很正常。你觉得哪里奇怪?
      

  2.   

    当执行这个的时候
    emp2.address.setNumber(2);//
    emp2.address.setState("美国");//原始类的赋值方法
    却和
    emp2.setAddress(new Address("美国", 2));
    两个执行的结果不一样,这是为什么?
      

  3.   

    现在终于发现问题所在:
    当代码中注释掉
    //emp2.address.setNumber(2);//
    //emp2.address.setState("美国");//原始类的赋值方法
    emp2.setAddress(new Address("美国", 2));
    打印结果符合预期的
    克隆之前:
    name:rollen, age:20 
    Address: state: 中国 munber: 1
    克隆之后
    ====重新设置对象emp2值=====
    name:rollen, age:20 
    Address: state: 中国 munber: 1
    -----
    name:hello world, age:100 
    Address: state: 美国 munber: 2反之
    当代码中注释掉
    emp2.address.setNumber(2);//
    emp2.address.setState("美国");//原始类的赋值方法
    //emp2.setAddress(new Address("美国", 2));
    克隆之前:
    name:rollen, age:20 
    Address: state: 中国 munber: 1
    克隆之后
    ====重新设置对象emp2值=====
    name:rollen, age:20 
    Address: state: 美国 munber: 2
    -----
    name:hello world, age:100 
    Address: state: 美国 munber: 2
    也就是说emp2.address.setState("美国")也改变了emp1的state 的值,emp2.address.setNumber(2)同理,这是为什么?
      

  4.   

    LZ对引用和对象概念模糊,你这个clone是浅克隆,所以
    emp1.adress和emp2.address指向同一个对象
    所以emp2.address.setXXX();改变emp2.address指向的对象的属性,emp1.address当然能看到变量了,因为它们看到是同一个对象
    而emp2.setAddress(new Address("美国", 2));
    是把emp2.address指向另一个新的new Address("美国", 2)对象,也就是说此时emp1.address和emp2.address不再指向相同的对象,那么emp2.adress怎么变化,也不会影响emp1.address,因为它们引用的是不同的两个对象。