Java趣味题

java是引用传递还是值传递?

结论,Java就是值传递,只不过在传递引用类型的时候,会把对象的引用地址当作值来传递。

首先声明一个引用类型:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private static class MyObject {

        private MyObject subObject;

        private String content;

        private int num;

        public MyObject(String content, int num) {
            this.content = content;
            this.num = num;
        }

        public MyObject(String content, int num, String subContent, int subnum) {
            this.content = content;
            this.num = num;
            this.subObject = new MyObject(subContent, subnum);
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder("当前的content是:" + content + "\t当前的num是" + num);
            if (subObject != null) {
                 sb.append("\n属性的content是:" + subObject.content + "\t属性的num是:" + subObject.num);
            }
            return sb.toString();
        }
    }

形参为一般类型,对实参无影响

1
2
3
4
5
6
public static void main(String[] args) throws Exception {

    int num = 0;
    test(num);
    System.out.println("经test方法之后,num值为:\n" + num);
}

输出:

1
2
经test方法之后,num值为:
0

形参为引用类型,对实参无影响

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public static void main(String[] args) throws Exception {

    MyObject obj = new MyObject("我是第一层", 10, "我是第二层", 20);
        test(obj);
        System.out.println("经test方法之后,obj对象为:\n" + String.valueOf(obj));
    }

    /**
     * 我是方法
     * @param myobj
     */
    private static void test(MyObject myobj) {
        myobj = null;
    }

输出:

1
2
3
test方法之后,obj对象为:
当前的content:我是第一层      当前的num10 
属性的content:我是第二层      属性的num:10

可以看到在方法中给形参设置为null,但是依然可以输出。

改变形参的一般类型字段,会改变实参的字段

1
2
3
private static void test(MyObject myobj) {
    myobj.num++;
}

输出:

1
2
3
经test方法之后,obj对象为:
当前的content是:我是第一层      当前的num是11
属性的content是:我是第二层      属性的num是:20

改变形参的引用字段,也会改变实参的字段

1
2
3
private static void test(MyObject myobj) {
    myobj.content = null;
}

输出:

1
2
3
经test方法之后,obj对象为:
当前的content是:null    当前的num是10
属性的content是:我是第二层      属性的num是:20

改变形参引用字段内部的一般字段,实参会变

1
2
3
private static void test(MyObject myobj) {
    myobj.subObject.num++;
}

输出:

1
2
3
经test方法之后,obj对象为:
当前的content是:我是第一层      当前的num是10
属性的content是:我是第二层      属性的num是:21

改变形参引用字段内部的引用字段,实参会变

1
2
3
private static void test(MyObject myobj) {
    myobj.subObject.content=null;
}

输出:

1
2
当前的content是:我是第一层      当前的num是10
属性的content是:null    属性的num是:20

总结:

java是拷贝传递,如果形参是引用类型,则改变形参对实参无任何影响;而改变形参内部的属性,则会对实参产生影响。

try里面return,是return先执行还是finally先执行?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public static void main(String[] args) throws Exception {
    boolean result = test();
    System.out.print("收到结果为:" + result);
}

private static boolean test() {
    try {
        System.out.println("执行到了return");
        return true;
    } finally {
        System.out.println("执行到了finally");
    }
}

输出:

1
2
3
执行到了return
执行到了finally
收到结果为:true

从输出上看,应该是先return再执行finally,但是…

当我在return处打上断点,在finally内部输出那一行也打上断点,调试时惊喜的发现,先执行try内的输出,然后自动跳过了return语句直接在finally内部的断点停了,当我继续运行,发现它又回到了return语句,最后才离开方法。

try和finally都return

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public static void main(String[] args) throws Exception {
    boolean result = test();
    System.out.println("收到结果为:" + result);
}

private static boolean test() {
    try {
        System.out.println("执行到了return");
        return true;
    } finally {
        System.out.println("执行到了finally");
        return false;
    }
}

当然到了现在,可以不相信输出了,要以断点顺序为准。

当try和finally中都有return时,Java再一次给了我惊喜:

首先执行了try中的return,然后又执行了finally中的return,最后才返回结果,并且是以finally中的return为准!

结论:

所以Java无论如何都是先finally再return