Обновить узел дерева с помощью передачи по значению в Java

Прежде чем я покажу свою проблему, я понимаю следующее: Java использует передачу по значению.

Сказал, что в примере ниже я передаю ссылку "my_root" в NodeModify (),

и в строке «NodeModify (my_root);» ожидайте, что компилятор передаст копию адреса памяти «my_root» и внутри функции make «root = new_node;» ie => ожидайте, что место / адрес в памяти root будет обновлено до / указывать на место, где находится "new_node".

Удивительно, но это не отражается в функции main (), откуда она была вызвана, почему это так?

package com.trees;

public class NodeExample {
    public static void NodeModify(Node root){
        System.out.println("[NodeModify] fresh root is : " + root);
        Node new_node = new Node(0);
        System.out.println("[NodeModify] new node is : " + new_node);
        root = new_node;
        System.out.println("[NodeModify] root is : " + root);
    }
    public static void main(String[]arg){
        Node my_root = new Node(55);
        System.out.println("my root before NodeModify is: " + my_root);
        NodeModify(my_root);
        System.out.println("my root after NodeModify is: " + my_root);
    }
}

Однако, если я сделаю то же самое с другой ссылкой, например ArrayList, она будет обновляться в main (), как я и ожидал! Пример:

package com.trees;

import java.util.ArrayList;

public class ArrayListUpdateClass {

    public static void updateMyArrayList(ArrayList<String> sample){
        sample.add("was updated!");
    }
    public static void main(String[]args){
        ArrayList<String> my_list = new ArrayList<String>();
        my_list.add("My list ");
        System.out.println("**Before call list is:**");
        printArrayList(my_list);
        updateMyArrayList(my_list);
        System.out.println("\n**After call list is:**");
        printArrayList(my_list);
    }
    private static void printArrayList(ArrayList<String> my_list) {
        for(String item:my_list){
            System.out.println(item);
        }

    }
}

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


person David Prun    schedule 22.04.2014    source источник
comment
Я наконец нашел ответ stackoverflow.com/questions/40480/   -  person David Prun    schedule 31.07.2014


Ответы (2)


Передача ссылки на метод означает, что ссылка является значением. Это значение предоставляется вам по имени параметра метода root, который находится в стеке. Назначение разных ссылок на параметр root будет отражаться только внутри метода, но как только вы выйдете из метода, все в стеке будет потеряно.

Вы хотите изменить значение, удерживаемое переменной my_root. Для этого вам нужно передать ссылку на переменную my_root, а не только значение, удерживаемое my_root. Это можно сделать, например, передав контейнер, содержащий ссылки на Nodes. Java Collection - один из таких контейнеров. Передача в контейнер и изменение его значений будет отражено вне метода NodeModify(Node root).

Некоторые примечания:

  • в Java метод должен начинаться со строчной буквы или символа подчеркивания
  • используйте верблюжий регистр для имен переменных вместо подчеркивания для разделения слов, кроме случаев, когда вы определяете константы
person Harmlezz    schedule 22.04.2014

Ваше замешательство происходит из-за того, что вы неверно истолковали вызов по значению.

[...] внутри функции make "root = new_node;" ie => ожидайте, что место в памяти / адрес root будет обновлено до / указывает на место, где "new_node" - [...]

Это точно описывало бы вызов по ссылке, чего - поскольку Java делает только вызов по значению - не происходит.

Основное различие между первым фрагментом кода и вторым: в первом примере вы повторно инициализировали параметр, присвоив ему новую ссылку. Это не отразится на вызывающей функции. Во втором примере вы разыменовываете параметр («.» Также известен как оператор разыменования), работающий с объектом по этой ссылке. Вызывающая функция и вызываемая функция имеют одну и ту же ссылку, поэтому при разыменовании обе работают с одним и тем же объектом.

Прочтите статью в Википедии о вызове по значению.

person Seelenvirtuose    schedule 22.04.2014