Java Передача по значению проблемы? - PullRequest
3 голосов
/ 17 декабря 2009

Мы знаем, что Java поддерживает только «передачу по значению». Если я передаю коллекцию, например, хеш-таблицу, функции, то изменения этой коллекции внутри функции не должны обновляться вне этой функции. Но это не так. случай в Java?. Как мы можем заключить это?

Пожалуйста, кто-нибудь завершит это обсуждение доказательством ...

Ответы [ 9 ]

8 голосов
/ 17 декабря 2009

Передача объекта по значению методу означает, что метод получает копию ссылки на объект, но все еще возможно получить доступ к членам объекта из переданной копии ссылки. В случае коллекций это включает в себя вызов методов для добавления и удаления объектов и, конечно, для изменения самих содержащихся объектов.

4 голосов
/ 17 декабря 2009

Вы путаете, что означает "ценность". Если вы имеете дело с объектами, это означает, что любые изменения значения ссылки не отражаются извне. Простой пример, демонстрирующий такое поведение, выглядит примерно так:

public void foo() {
  String s = "example";
  String param = s;
  bar(param);
  assert s == param : "The value of parameter reference was not modified";
  assert param.equals("example");
}

public void bar(String param) {
  param = "something different";
}

Передача по значению, однако, не означает, что вы не можете изменить внутреннее состояние объекта. Это вполне возможно и имеет последствия для внешней среды:

public void foo() {
  List<String> l = Arrays.asList("example");
  List<String> param = l;
  bar(param);
  assert s == param : "The value of parameter reference was not modified";
  assert !param.get(0).equals("example") : "bar changed the internal state of the parameter";
  assert !l.get(0).equals("example") : "bar changed the internal state of the list that is reference equal to the parameter";
}

public void bar(List<String> param) {
  param.set(0, "something different");
}

Конечно, такие изменения внутреннего состояния объекта полностью отражаются в стеке вызывающего, что может привести к непредвиденным побочным эффектам. Это причина, по которой был введен шаблон неизменяемого объекта . В стандартной библиотеке Java java.lang.Object и java.lang.String являются примерами для классов, которые реализуют этот шаблон. Однако в Java нет языковой функции, позволяющей утверждать, что класс реализует этот шаблон, поэтому вы должны полагаться на JavaDoc и / или исходный код класса, чтобы быть уверенным, что объект неизменен.

3 голосов
/ 17 декабря 2009

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

2 голосов
/ 17 декабря 2009

Хотя это «передача по значению» - в случае переменных примитивов значение переменной копируется в функцию. В случае ссылок на объекты, которые в случае Hash-таблицы имеют значение true, передается значение в ссылке, которое является ничем иным, как адресом объекта в куче. Таким образом, ссылка на функцию, к которой вы передаете «хеш-таблицу», фактически получает копию адреса объекта хеш-таблицы. Так что все изменения, сделанные с помощью функции, отражаются в основном объекте.

1 голос
/ 17 декабря 2009

Доказательство:

public static void main(String[] args) {
    int i = 1;
    addOne(i);
    System.out.println("after addOne: " + i);

    // now for Objects
    String text = "a text";
    addText(text);
    System.out.println("after addText: " + text);
}


private static void addOne(int i) {
    i += 1;
    System.out.println("in addOne: " + i);
}

private static void addText(String text) {
    text += ", more text";
    System.out.println("in addText: " + text);
}

должно привести к

in addOne: 2
after addOne: 1
in addText: a text, more text
after addText: a text

как видите переменные в main не меняются, то есть переменная передается по значению.

1 голос
/ 17 декабря 2009

В Java вы никогда не передаете Объекты, вы только передаете ссылки / указатели на Объекты. Так в звонилке

Object x = new Object();
int y = 42;

foo(x,y)

передается значение x, то есть (ссылка на) Object, а также значение y, целое число 42. «Передача по ссылке» будет означать, что вы можете изменить значение переменных, x и у, без foo ().

0 голосов
/ 02 января 2013

Java передается по значению , но когда мы передаем ссылку на объект, ссылочное значение передается методу get, и оттуда метод может изменить значение членов объекта.

Посмотрите на следующий код

открытый класс Passbyvalue {

public static void main(String[] args) {
    // TODO code application logic here
    Animal animal=new Animal();
    animal.name="Dog";
    System.out.println(animal.name);
    testIt(animal);
    System.out.println(animal.name);
}


public static void testIt(Animal animal){
    animal.name="Cat";
}

}

Выход

Собака Cat

Это потому, что обе ссылки (оригинал и метод) указывают на один и тот же объект.

    __________
   |          |                 
   |          |<------------- Orignal Refernce 
   | Object   |   
   |          |<------------- Method Refernce
   |          |
   |__________|

Если вы хотите увидеть этот эффект более четко, создайте новый объект в методе

открытый класс Passbyvalue {

public static void main(String[] args) {
    Animal animal=new Animal();
    animal.name="Dog";
    System.out.println(animal.name);
    testIt(animal);
    System.out.println(animal.name);
}


public static void testIt(Animal animal){
    animal=new Animal();
    animal.name="Cat";
}

}

Выход Собака Собака

Теперь ссылка на метод ссылается на другой объект в куче.

    __________
   |          |                 
   |          |
   | Orignal  |<------------- Orignal Refernce    
   | Object   |
   |          |
   |__________|



    __________
   |          |                 
   |          |
   | Method   |<------------- Method Refernce    
   | Object   |
   |          |
   |__________|

Надеюсь, это поможет

0 голосов
/ 17 декабря 2009

в чем смысл этого обсуждения?

если вы хотите защитить свои аргументы, переданные другим методам, то juz следует комментарию Тило, и все

0 голосов
/ 17 декабря 2009

Вот отличная запись с некоторыми примерами. http://javadude.com/articles/passbyvalue.htm

Вот мой простой взгляд на проблему. Java всегда является языком передачи по значению. Это помогает думать об этом как о языке передачи по ссылке при разговоре об объектах. НО это не совсем так. То, что он делает, передает значение адреса памяти.

РЕДАКТИРОВАТЬ: Спасибо за отрицательные голоса. Возможно, вам следовало сначала прочитать статью. Поскольку никто не имеет воли дать пример:

public class Dog {

    public String name;

    public Dog(String name) {
        this.name = name;
    }

    public static void main(String []args) {

        Dog newDog = new Dog("Max");
        newDog.test(newDog);
        System.out.println(newDog.name);

    }

    public void test(Dog dog) {
        dog = new Dog("Gotcha");
    }

}

Так что же вышеперечисленное выводит на консоль? Теперь, если вы, ребята, кричали, что передача по ссылке была правильной, она напечатала бы «Gotcha», но не напечатала «Max». Но подождите, это точно так же, как поведение с передачей по значению. Но почему? Потому что в Java объекты не передаются по ссылке. Правильное утверждение: ссылки на объекты передаются по значению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...