方法更改对象

时间:2015-11-10 13:55:24

标签: java

你能解释一下这段代码的行为:

class Test{
    public List<String> change(List<String> s){
        List<String> tmp = s;
        tmp.add("test");
        return tmp;
    }

    public Integer change(Integer s){
        Integer tmp = s;
        tmp++;
        return tmp;
    }
}


public class Main {

    public static void main(String[] args)  {

        List<String> l = new ArrayList<String>();
        Integer i = new Integer(10);

        Test t = new Test();

        System.out.println(l);
        t.change(l);
        System.out.println(l);

        System.out.println(i);
        t.change(i);
        System.out.println(i);

    }
}

结果是:

[]
[test]
10
10

为什么我的列表被更改,即使在change()方法内部我创建了tmp变量并归因于它传递了参数而我的Integer在相同的情况下没有变化?

4 个答案:

答案 0 :(得分:3)

诀窍在于:

    Integer tmp = s;
    tmp++;

这大致相当于*:

    Integer tmp = s;
    int tmp_unboxed = tmp.intValue;
    tmp_unboxed++;
    tmp = new Integer( tmp_unboxed );

Integer unboxedint,然后int会递增,最后结果为boxed到另一个Integer对象

如您所见,原始整数尚未修改,而是创建了一个新整数。而在列表示例中,您可以修改原始列表。

*我过度简化了这种情况,以便更轻松地解决问题:特别是你不总是得到一个全新的Integer个实例,但你总是得到一个不同的 { {1}}实例比你开始时的实例..

答案 1 :(得分:1)

这是因为Integer(与String,Double等相同)是不可变的。这意味着你无法改变该对象的价值。

那么这里会发生什么?

if (isset($_GET['id']) && is_numeric($_GET['id']))
    {   
$id = $_GET['id'];
if ( $stmt3 = $mysqli->query ( "INSERT INTO tbluser (username,  password,email,role = 1) SELECT companyUsername,companyPassword,companyEmail  FROM tblpartner WHERE companyId=?" ));
        }

在这一行Integer tmp = s; tmp++; ,Integer的实例(我们可以称之为X)在内存中,对它的引用存储在变量Integer tmp = s;中。您将此X引用复制到变量s

在这一行tmp中,因为Integer是不可变的,所以新实例Y在内存中创建,它被赋予实例X的值,然后递增,然后对它的引用存储在变量{{1 }}

变量X仍在内存中且值不变。

答案 2 :(得分:1)

整数对象是不可变的。从

中捕获结果
int returnedObject = t.change(i);

并打印returnedObject,您将看到修改后的对象

另一方面,列表对象是可变的。这就是为什么变化反映在同一个对象本身

答案 3 :(得分:1)

这是由于java的两个特性:autoboxing和pass-by-reference。

传递引用意味着如果将Object用作方法的参数,则将其在内存中的位置传递给该方法。因此,作为参数传递的List被修改。

Integer也是通过引用传递的,但是这里的autoboxing适用。 Integer本身是Object,不支持运营商; Integer是不可改变的!自动装箱将Integer或基元类型的对象表示转换为基元类型。因此,Integer转换为intint被修改。但是,此操作不会影响Integer - 对象。 Integer中的change基本上可以用这种方式大致描述:

public Integer change(Integer s){
    //store reference to `s` in tmp
    Integer tmp = s;

    //unbox tmp and increment
    tmp++;

    //return tmp
    return tmp;
}

Unboxing:
int unboxed = tmp.intValue();
unboxed++;
tmp = new Integer(unboxed);