1

下面是我几乎没有疑问的代码,因为在 JAVA 中没有按引用传递或按地址传递。那为什么调用方法后输出会发生变化?并且还想知道方法调用后的 JAVA 内部机制?

class Language
{
    String languageID;
    String name;

    public Language(){}

    public Language(String id, String name)
    {
        this.languageID = id;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Language id-->" + languageID + " Name-->" + name;
    }
}

public class SwapDemo {
    public static void swap()
    {
        int a = 10, b= 5;
        System.out.println("Before Swap : A-"+a+" B-"+b);
        a = a+b;
        b = a-b;
        a = a-b;
        System.out.println("After Swap : A-"+a+" B-"+b);
        a = a^b;
        b = a^b;
        a = a^b;
        System.out.println("After Swap : A-"+a+" B-"+b);
    }

    public static void swap(Language e1, Language e2)
    {
        Language temp = new Language();
        temp = e1;
        e1 = e2;
        e2 = temp;
    }

    public static Language method(Language addit)
    {
        addit.name = "C++";
        addit = new Language();
        addit.name = "Harshal";
        return addit;
    }

    public static void main(String[] args) {
        Language l1 = new Language("1", "C");
        Language l2 = new Language("2", "Java");

        System.out.println("Before swap of employees");
        System.out.println("Language 1-----> "+l1.toString());
        System.out.println("Language 2-----> "+l2.toString());

        swap(l1, l2);
        System.out.println("After swap of employees");
        System.out.println("Language 1-----> "+l1.toString());
        System.out.println("Language 2-----> "+l2.toString());

        Language t = method(l1);
        System.out.println("Changing "+ l1.name);
        System.out.println("Changing "+ t.name);
    }
}
4

3 回答 3

0

数字

我正在解释以下几行,这将消除您的疑问。我假设您对堆和堆栈有所了解。

        Language t = method(l1);
        System.out.println("Changing "+ l1.name);
        System.out.println("Changing "+ t.name);

在这里,当您将“l1”对象传递给方法时,您将REFERENCE传递给对象。REFERENCE是一种句柄,用于识别HEAP SPACE中的对象。

考虑,

A a =new A();

这里将包含什么?显然一些地址指向新创建的对象

因此,当您将 OBJECT 传递给方法时,您正在传递对对象所在内存位置的引用。但是在方法内部,如果您尝试将对象更改为其他对象,就像您在 swap(l1,l2) 方法中所做的那样,它将失败,因为您正在更改地址的值,而不是实际的对象

因此,语句addit.name="C++" 将更改驻留在 addit 指向的内存位置的对象的内容。因此这里的原始对象已被修改。希望这可以消除您的第一个疑问。

关于您的第二个疑问,一个对象正在其范围内。一旦方法调用结束,在该方法中分配的所有变量都有资格被垃圾收集。但是在这里,您正在执行的操作是从方法返回对对象的引用。所以对象不会被垃圾回收,因为它有指向它的有效引用。因此,在第二个输出中它会打印新值。希望这有助于理解输出。

于 2013-05-16T10:36:23.727 回答
0

Java 是按值传递的。它将引用的副本传递给方法。所以这意味着:

List<String> l = new ArrayList<String>();
someMethod(l);

某些方法刚刚获得了 l 的副本——它是对堆上 ArrayList 的引用。

public void someMethod(List<String> aList) {
    aList.add("Foo");
}

someMethod 可以将内容添加到该列表中,因为本地引用 aList 在调用者范围内指向与“l”相同的对象。但是请注意:

public void someMethod(List<String> aList) {
    aList = new LinkedList<String>();
}

对调用者没有影响,所有这些都是使本地变量“aList”指向堆上的不同对象。请记住,aList 是我们调用该方法的引用的副本,因此它们都引用了同一个堆对象,重新分配后它们不再这样做。

于 2013-05-16T10:28:44.760 回答
0

问题的前提是有缺陷的。您不能在 Java 中“传递对象”。Java 中唯一的类型是原始类型和引用类型,因此唯一的值是原始类型和引用。“对象”不是值,不能传递。对象只能通过指向它们的引用来操作。在您的代码中l1l2, 等是引用。

于 2013-05-18T00:03:29.737 回答