前两天在做项目开发的时候,想要对一个两百行的方法重构,让它的体积缩小一点.于是我就把代码做了一下调整(下面的是举例):
public class QuoteTest {
public void test() {
Demo demo = null;
demo = QuoteTest.getDemo();
}
public static Demo getDemo() {
return new Demo();
}
}
class Demo{
private Integer integer;
private int i;
private InnerDemo innerDemo;
}
class InnerDemo {
}
上面的例子里面,在test方法里首先建立了一个Demo对象的引用,值为null,在后续的方法当中将获取到的demo的值传递给了这个引用.当然,实际的代码中这个过程有四十多行代码,这里只是为了演示而进行了简化,这个获取值的过程,我希望将它封装到一个private的方法中去来减少代码的行数,于是变成了下面这样:
public class QuoteTest {
public void test() {
QuoteTest quoteTest = new QuoteTest();
Demo demo = null;
// demo = QuoteTest.getDemo();
quoteTest.putValue(demo);
System.out.println(demo);
}
public static Demo getDemo() {
return new Demo();
}
private void putValue(Demo demo) {
demo = QuoteTest.getDemo();
}
public static void main(String[] args) {
QuoteTest quoteTest = new QuoteTest();
quoteTest.test();
}
}
class Demo{
private Integer integer;
private int i;
private InnerDemo innerDemo;
}
class InnerDemo {
}
//output
//null
很清楚的看到,现在我改为了调用私有方法对demo进行赋值.原本以为万事大吉.但是,实际情况确实这个时候demo的值还是null.于是我就去百度和google查找答案,原来是因为,java当中只有值传递,没有引用传递,对于基本类型,将基本对象的值传入给方法,对于对象,将对象的引用传入给方法.传入后,方法中的对象引用与方法外的其实已经没有什么关系,对于基本类型来说,无论你如何修改基本类型的值,方法外部的基本类型的值都不会发生改变:
public class QuoteTest {
public void test(int i) {
i = i * 10;
System.out.println("in test():" + i);
}
public static void main(String[] args) {
int i = 10;
System.out.println("before test():" + i);
QuoteTest quoteTest = new QuoteTest();
quoteTest.test(i);
System.out.println("after test():" + i);
}
}
//out put
//before test():10
//in test():100
//after test():10
对于引用类型,我们都知道, A a = new A();这句话会产生两个对象,a指向 new A() 的地址,传入方法的值也是地址,由于传入后对象指向的地址和方法外对象指向的地址是同一个,因此对这个地址内的值进行操作,方法外的对象也会同步的发生修改,造成了java中有引用传递的错觉.如果是改变方法内对象的地址引用,那么对于方法外的对象是产生不了任何影响的.也因此产生了上面所说的问题
之后我又产生了一个新的问题,既然这样,为什么操作地址内的对象就可以了呢?可以看到Demo对象中有一个InnerDemo,无论在哪里修改这个innerDemo的值,都会对外面的对象进行修改.因为是对地址内的值进行修改,无论在何处修改,都是修改同一个对象.