Помогите, пожалуйста разобраться с ссылками в java.
Вот хороший пример:
public class TestClass {
public static void main(String[] args) {
int a = 7;
String s = "asd";
Person p = new Person("bb1", 6);
method1(a);
method2(s);
method3(p);
System.out.println(a); //7 - это потому что не было присваивания, верно?
System.out.println(s); //asd - тут тоже вроде бы понятно
System.out.println(p); //qwerty - а вот тут - почему только тут содержимое объекта меняется?
}
public static void method1(int a) {
++a;
a++;
}
public static void method2(String s) {
s = "bfr";
}
public static void method3(Person p) {
p.setName("qwerty");
}
}
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " " + age;
}
public void setName(String name) {
this.name = name;
}
}
Все параметры метода передаются в джаве по значению.
1) передавая примитив в метод, значение просто копируется
public static void method1(int a) {
++a;
a++;
}
т.е. внутри метода создается локальная переменная с именем а, и ее изменение никак не влияет на состояние переменой а в методе main
2) Передавая в метод параметр ссылочного типа, вы передаете копию указателя.
public static void method2(String s) {
s = "bfr";
}
т.е. s - это какое-то значение 0xA12s, оно указывает на обьект в памяти "asd", и когда вы передаете s в метода, копируется само значение указателя 0xA12s. Т.е. по факту тоже самое что с int. Т.е. от того, что вы измените ссылку s на 0x12abc ничего не изменится, потому что это внутри метода мейн ссылка останется прежней.
3) Когда вы передаете Person, опять же тупо копируются ссылка на этот обьект.
public static void method3(Person p) {
p.setName("qwerty");
}
Т.е. внутри main p=0x123 -> (какая-то область в памяти) и
внутри method3 p=0x123 -> (та же область в памяти)
когда вы вызываете сеттер идет разименование ссылки, вызывается метод на том обьекте, ссылку на который вы передали. И меняется его значение в пямяти, т.е.
до : p=0x123 -> ("bb1", 6)
после: p=0x123 -> ("qwerty", 6)
т.е. когда метод закончился указатель все еще смотрит на туже область в памяти только теперь, там в поле имя, вместо ссылки на бб1 ссылка на кверти.
Рекоммендую включить гугл транслейт и обратиться к похожим вопросам: http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value
Если у вас имеется некоторый метод, как, например, этот
public static void method2(String parameter) {
parameter = "bfr";
}
И вы его вызываете как
String argument = "asd";
method2( argument);
то параметр метода инициализируется аргументом, указанным при вызове. То есть это можно представить себе следующим образом
public static void method2( /*String parameter*/) {
String parameter = argument;
parameter = "bfr";
}
Как видно, в методе меняется значение переменной parameter. Сначала ей присваивается значение переменной argument, а затем новое значение строкового литерала "bfr"
Сама исходная переменная argument не изменилась. Ей ничего не было присвоено.
Что касается этого метода
public static void method3(Person p) {
p.setName("qwerty");
}
то здесь также параметр с именем p получил копию значения своего аргумента. Сам аргумент в методе не меняется. Но так как после вызова функции параметр, получивший значение аргумента, указывает на тот же самый объект, что и аргумент, то с его помощью можно изменить адресуемый объект.
То есть в этом методе изменяется не аргумент, а объект, на который ссылается аргумент, так как параметр получает ту же самую ссылку на объект.
int - примитивный тип, а вот s уже такой же экземпляр класса String, как и p экземпляр класса Person (именно поэтому String пишется с большой буквы) и в метод передается ссылка на ячейку памяти.
Класс String по сути массив символов.
Но у Stringa есть несколько ньюансов в инициализации. Так например:
s1='string';
s2='string';
s1==s2; // true
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости