поменяйте местами два номера с помощью вызова по ссылке - PullRequest
2 голосов
/ 20 февраля 2012

Можем ли мы поменять два числа в Java, используя передачу по ссылке или вызов по ссылке?Недавно, когда я столкнулся с обменом двух чисел в Java, я написал

class Swap{
    int a,b;
    void getNos(){
        System.out.println("input nos");
        a = scan.nextInt();
        b = scan.nextInt(); // where scan is object of scanner class
    }
    void swap(){
        int temp;
        temp = this.a;
        this.a = thisb;
        this.b = this.a;
    }
}

. В основном методе я вызываю вышеупомянутые методы и беру два целых числа a, b, а затем, используя второй метод, меняю местамидва числа, но относительно самого объекта ....

Эта программа или логика проходит мимо ссылки?И это правильное решение?

1 Ответ

6 голосов
/ 20 февраля 2012

Да и нет. Java никогда не передается по ссылке, и ваш путь - один из обходных путей. Но все же вы создаете класс, чтобы поменять местами два целых числа. Вместо этого вы можете создать оболочку int и использовать ее, таким образом, целое число может быть отделено, когда не нужно:

public class IntWrapper {
    public int value;
}

// Somewhere else
public void swap(IntWrapper a, IntWrapper b) {
    int temp = a.value;
    a.value = b.value;
    b.value = temp;
}

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

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

Например, если Java передавалась по ссылке, следующий код выведет x = 1:

public class Example {
    private static void bar(int y) {
        y = 10;
    }
    public static void main(String[] args) {
        int x = 1;
        bar(x);
        System.out.println("x = " + x);
    }
}

Но, как мы знаем, он печатает 0, поскольку аргумент, переданный методу bar , является копией оригинала x, и любое присвоение ему не повлияет на x.

То же самое относится и к следующей программе на C:

static void bar(int y) {
    y = 1;
}
int main(int argc, char * argc[]) {
    int x = 0;
    bar(x);
    printf("x = %d\n", x);
}

Если мы хотим изменить значение x, нам нужно будет передать его ссылку (адрес), как в следующем примере, но даже в этом случае мы не передадим фактическую ссылку, но копия ссылки, и разыменовывая ее, мы сможем изменить фактическое значение x. Тем не менее, прямое назначение ссылки не изменит самой ссылки, так как она передается по значению:

static void bar(int &y) {
    *y = 1;
    y = NULL;
}
int main(int argc, char * argc[]) {
    int x = 0;
    int * px = &x;
    bar(px);
    printf("x = %d\n", x); // now it will print 1
    printf("px = %p\n", px); // this will still print the original address of x, not 0
}

Таким образом, передача адреса переменной вместо самой переменной решает проблему в C. Но в Java, поскольку у нас нет адресов, нам нужно обернуть переменную, когда мы хотим присвоить ей. В случае только изменения объекта у нас нет этой проблемы, но, опять же, если мы хотим присвоить ему, мы должны обернуть его, как в первом примере. Это относится не только к примитивам, но и к объектам, включая те объекты-обертки, которые я только что упомянул. Я покажу это в одном (более длинном) примере:

public class Wrapper {
    int value;
    private static changeValue(Wrapper w) {
        w.value = 1;
    }
    private static assignWrapper(Wrapper w) {
        w = new Wrapper();
        w.value = 2;
    }
    public static void main(String[] args) {
        Wrapper wrapper = new Wrapper();
        wrapper.value = 0;
        changeValue(wrapper);
        System.out.println("wrapper.value = " + wrapper.value); 
        // will print wrapper.value = 1
        assignWrapper(w);
        System.out.println("wrapper.value = " + wrapper.value); 
        // will still print wrapper.value = 1
    }
}

Ну, вот и все, надеюсь, я ясно дал понять (и не сделал слишком много ошибок)

...