2013-05-27 2 views
1

После тестирования кода (см. Ниже), я узнал, что я не понимаю некоторые основы.Явное понимание копирования копий

Класс А.

class A { 

    private String s; 
    private int[] array; 
    private B b; 

    public A(String s, int[] array, B b) { 
     this.s = s; 
     this.array = array; 
     this.b = b; 
    } 
} 

Класс B.

class B { 

    public int t; 

    public B(int t) { 
     this.t = t; 
    } 

} 

Я думал, что любые изменения, которые я сделал после того, как A a = new A(s, array, b); затронет a. Не все поля a и переменные s, array, b обратитесь к тому же объекту?

String s = "Lorem"; 
    int array[] = new int[] { 
      10, 20, 30 
    }; 
    B b = new B(12); 
    A a = new A(s, array, b); 
    s = "Dolor"; 
    array = new int[] { 
      23 
    }; 
    b = new B(777); // Initialized with a new value, a.b keeps the old one. Why? 
    System.out.println(a); 

Выход.

String Lorem 
Array [10, 20, 30] 
B 12 

И об этом.

B b2 = new B(89); 
B b3 = b2; 
System.out.println(b3); 
b2 = null; 
System.out.println(b3); // b2 initialized with null, b3 keeps the old one. Why? 

Выход.

89 
89 

Однако, если у меня есть два списка, это показывает, что оба они относятся к тому же объекту.

ArrayList<String> first = new ArrayList<String>(); 
    first.add("Ipsum"); 
    ArrayList<String> second = new ArrayList<String>(); 
    second = first; 
    first.add("The Earth"); 
    System.out.println(second); 

Выход.

[Ipsum, The Earth] 

ответ

4

Разница присвоение по сравнению с модификация.

Назначение (=) делает переменную точкой для чего-то еще, поэтому это не изменит базовые данные. Поэтому любые другие переменные, указывающие на одни и те же данные, не изменяются.

Модификация (почти все, кроме =) не изменяет то, на что указывает переменная, она просто изменяет базовый объект. Поэтому любые другие переменные, указывающие на одни и те же данные, изменяются.

Для вас, например:

b = new B(777); это назначение, поэтому только b изменяется, чтобы указать на что-то другое. a.b не изменится.

b2 = null; является присвоением, поэтому только b2 изменен, чтобы указать на что-то еще. b3 не изменится.

Если вы должны были сказать b2.t = 5, это будет модификация (мы не назначая новое значение b2, мы его модификации путем изменения одного из ее членов), так b3 будет меняться.

Я надеюсь, что это объяснит.

+0

Теперь это ясно. Две переменные относятся к одному и тому же объекту. Если I ** изменить ** прежнюю переменную, последняя будет затронута. Если я просто ** назначу ** новое значение для первой переменной, оно будет ссылаться на новый объект, последний сохранит старую ссылку (и старое значение) –

1

Нет. Дело в том, что вы не меняя, вы присваиваете новое значение с. S - это строка, неизменяемая, что означает, что вы никогда не сможете изменить значение s. Однако вы можете изменить ссылку в S, что и есть то, что вы делаете.

+0

спасибо. 'array [0] = 4444;' повлияет на 'a' (я только что протестировал). Я не понимал разницы между назначением и модификацией (Dukeling, большое спасибо). –

0

Спасибо Dukeling за разъяснение того, как задания работают с объектами и примитивами, я добавляю здесь, чтобы объяснить, как работает список при выполнении операций над ними.

Когда мы рассматриваем два списка массива, созданных в коде выше в вопросе, как переменные первого и второй указывают на тот же объект массива, который находится в памяти.

Итак, когда выполняется операция добавления, базовый объект сам обновляется. Таким образом, операция печати печатает список второй, который указывает на тот же объект списка массивов, созданный при создании первого списка.

1

Чтобы сделать себя более ясно попробовать эти строки кода ..

String s = "Lorem"; 
int array[] = new int[] {10, 20, 30}; 
B b = new B(12); 
//A a = new A(s, array, b); 

s = "Dolor"; 
array = new int[] {23}; 
b = new B(777); 
A a = new A(s, array, b); 
System.out.println(a); 


ArrayList<String> first = new ArrayList<String>(); 
first.add("Ipsum"); 
ArrayList<String> second = new ArrayList<String>(); 
second = first; 
second.add("The Earth"); 
first.remove("The Earth"); 
System.out.println("second :"+second); 

Каковы текущие значения Строка с, массив и объект б хранящие при создании экземпляра класса А (в то время конструктора вызывающего класса A). После создания экземпляра класса A строковые s, массив и объект b будут называться a.s, a.array и т. Д. Если вы присвоите новое значение s, массиву и b, это не повлияет на экземпляр класса A.

И для вопроса списка массива два списка массивов будут ссылаться только на одну и ту же ссылку. Если вам нужна другая ссылка, тогда сделайте так ... (Но всегда = присваивать оператор будет делать только эту ссылку)

ArrayList<String> first = new ArrayList<String>(); 
    first.add("Ipsum"); 
    ArrayList<String> second = new ArrayList<String>(first); 
    second.add("The Earth"); 
    System.out.println("first :"+first);   
    System.out.println("second :"+second);  
+0

's =« Долор »; array = new int [] {23}; b = новый B (777); A a = новый A (s, массив, b); System.out.println (a); 'Все _variables_ (' s', 'array',' b') потеряли свои старые _references_ (я еще не уверен в терминологии) после того, как вы вызвали 'new' (назначение). Если бы существовала примитивная переменная типа (например, 'int'), она потеряла бы ее _value_. Оба списка - _reference variables_ и относятся к одному и тому же _объекту_. И если вы измените прежний список, будет затронута буква, относящаяся к одному и тому же объекту. –

+0

У меня есть файл изображения, чтобы объяснить это. Но я не могу загрузить его здесь. Если вы хотите, я поделюсь им с u по электронной почте. – Karthi

+0

будет очень любезно с вашей стороны. Вы можете видеть мой профиль, там есть электронная почта –

Смежные вопросы