try{}catch{}finally{} 语句块中返回值顺序,Java 值传递引用传递的区别


GitHub 示例代码地址 : https://github.com/GourdErwa/my_note/tree/master/src/main/java/com/java/Basis/grammar


try{}

catch{}

finally{}

语句块都有 return 时候对于基本数据类型和引用数据类型怎么处理?why?


先看几个 example


/**
     * 基本数据类型
     * try{}中有异常测试
     *
     * @return int
     */
    private static int primitiveTypeHasException() {
        int temp = 0;
        try {
            temp = temp / 0;
            System.out.println("not have Exception ,return 0");
            return temp++;
        } catch (Exception e) {
            temp += 100;
            System.out.println("run  catch{ temp += 100; }  temp=" + temp);
            return temp;
        } finally {
            temp++;
            System.out.println("run  finally{   temp++;  }  temp=" + temp);
        }
    }
    /*
    执行结果:
    run  catch{ temp += 100; }  temp=100
    run  finally{   temp++;  }  temp=101
    return : 100
     */
分析过程:try 中抛出异常到 catch 语句块,执行+100操作后为temp=100 return 100.
然后执行 finally 语句块,temp++后为101


/**
     * 基本数据类型
     * try{}中有异常测试
     *
     * @return int
     */
    private static int primitiveTypeHasException() {
        int temp = 0;
        try {
            temp = temp / 0;
            System.out.println("not have Exception ,return 0");
            return temp++;
        } catch (Exception e) {
            temp += 100;
            System.out.println("run  catch{ temp += 100; }  temp=" + temp);
            return temp;
        } finally {
            temp++;
            System.out.println("run  finally{   temp++;  }  temp=" + temp);
            return temp;
        }
    }

分析过程:不同于上例中的时 finally 中也有 return 语句了
执行过程如下,直接在 finally 中返回了
run  catch{ temp += 100; }  temp=100
run  finally{   temp++;  }  temp=101
return : 101



 /**
     * 引用类型
     * try{}中有异常测试
     *
     * @return Map
     */
    public static Map<String, String> stringMapHasException() {
        Map<String, String> map = new HashMap<>();
        map.put("Key", "init");
        try {
            int temp = 1 / 0;
            return map;
        } catch (Exception e) {
            map.put("Key", "catch");
            System.out.println("run catch{map.put(\"Key\", \"catch\");}  map=" + map);
            return map;
        } finally {
            map.put("Key", "finally");
            map = null;
            System.out.println("run finally{ map.put(\"Key\", \"finally\"); map = null;} ,  map=" + map);
            //return map;
        }
    }
    /*
    执行结果:
    run catch{map.put("Key", "catch");}  map={Key=catch}
    run finally{ map.put("Key", "finally"); map = null;} ,  map=null
    return : {Key=finally}
     */

分析过程:try 抛出异常跳到 catch put 了一个值后 return map ,然后执行 finally put 了一个新值后引用指向 null 
最终catch 返回的是 finally 修改map值后的对象,而没有返回 null

当然,如果把 finally 中的 return map; 语句注释去掉,最终会返回 null,因为 Java 是值传递而不是引用传递。


总结以上示例:


①: finally块的语句在try或catch中的return语句执行之后返回之前执行且finally里的修改语句可能影响也可能不影响try或catch中 return已经确定的返回值,
  因为如果finally里也有return语句则覆盖try或catch中的return语句直接返回。

②:finally块的语句在try或catch外的return语句执行之后返回之前执行且finally里的修改语句影响try或catch外 return的返回值

可能影响也可能不影响的原因是 Java 是值传递而不是引用传递

值传递和引用传递示例代码


/**
 * JAVA 值传递 or 引用传递 example
 *
 * @author wei.Li by 14-9-3.
 */
public class ValueOrQuoteTransfer {

    public int id;
    public String name;

    public ValueOrQuoteTransfer() {
    }

    public ValueOrQuoteTransfer(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("ValueOrQuoteTransfer{");
        sb.append("id=").append(id);
        sb.append(", name='").append(name).append('\'');
        sb.append('}');
        return sb.toString();
    }

    /**
     * @return 初始化一个对象
     */
    private static ValueOrQuoteTransfer init() {
        return new ValueOrQuoteTransfer(1, "init");
    }


    /**
     * 参数传入对象,只修改他的值,不改变引用
     *
     * @param transfer 测试对象
     */
    private static void updateObjectValue(ValueOrQuoteTransfer transfer) {
        transfer.name = "updateObjectValue";
    }

    /**
     * 参数传入对象,只改变引用
     *
     * @param transfer 测试对象
     */
    private static void updateObjectTransfer(ValueOrQuoteTransfer transfer) {

        transfer = new ValueOrQuoteTransfer(2, "TWO");
    }

    public static void main(String[] args) {

        /**
         * 参数传入对象,只修改他的值,不改变引用 test 结果
         *
         * updateObjectValue before    is  :ValueOrQuoteTransfer{id=1, name='init'}
         * updateObjectValue after     is  :ValueOrQuoteTransfer{id=1, name='updateObjectValue'}
         */
        ValueOrQuoteTransfer transfer = init();
        System.out.println("updateObjectValue before    is  :" + transfer);
        updateObjectValue(transfer);
        System.out.println("updateObjectValue after     is  :" + transfer);

        /**
         * 参数传入对象,只改变引用 test
         *
         * updateObjectTransfer before is   :ValueOrQuoteTransfer{id=1, name='init'}
         * updateObjectTransfer after  is   :ValueOrQuoteTransfer{id=1, name='init'}
         */
        ValueOrQuoteTransfer transfer1 = init();
        System.out.println("updateObjectTransfer before is   :" + transfer1);
        updateObjectTransfer(transfer1);
        System.out.println("updateObjectTransfer after  is   :" + transfer1);

    }

}

示例结果分析:


1.当我们在方法参数传入基本数据类型后,改变值不改变传入的值

2.当传入的是引用类型数据时候,就会可能改变传入的对象值,1.直接修改引用对象的值时候会改变,2.改变对象的引用的时候不改变传入的对象值。

传入引用对象其实是 copy 了一份引用对象的地址给方法中的形参,2个地址指向同一对象,修改值时候当然互相影响

如果是形参的引用地址改变了,例如执行 map = null; 或者 map = 其它 map;引用地址不和传入的对象一个指向了,当然不会互相影响


对于重构来说,推荐"移除对参数的赋值"  Remove Assignments to Parameters


最后一个示例证明2个地址指向同一对象


main 方法执行 transfer2为初始化的一个对象,起线程一直修改实参对象的值  1s 修改一次

ValueOrQuoteTransfer transfer2 = init();
        updateObject2Thread(transfer2);//方法内部起一线程一直打印 引用对象[transfer2] 的值
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000L);
                        transfer2.name = UUID.randomUUID().toString();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

updateObject2Thread方法 //方法内部一直打印传入的实参对象 0.5s 打印一次

   /**
     * Thread 0.5s 打印一次传入的对象 transfer
     *
     * @param transfer 测试对象
     */
    private static void updateObject2Thread(ValueOrQuoteTransfer transfer) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(500L);
                        System.out.println(transfer);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

执行结果


  ValueOrQuoteTransfer{id=1, name='init'}
         ValueOrQuoteTransfer{id=1, name='init'}
         ValueOrQuoteTransfer{id=1, name='99aade6b-cfc5-44d6-8ac7-66394493aaa9'}
         ValueOrQuoteTransfer{id=1, name='99aade6b-cfc5-44d6-8ac7-66394493aaa9'}
         ValueOrQuoteTransfer{id=1, name='79b71dc2-aa78-41ed-a54b-4d7b2fcfee04'}
         ValueOrQuoteTransfer{id=1, name='79b71dc2-aa78-41ed-a54b-4d7b2fcfee04'}
         ValueOrQuoteTransfer{id=1, name='16b5db8d-0376-4403-9d59-3252a6c00660'}
         ValueOrQuoteTransfer{id=1, name='16b5db8d-0376-4403-9d59-3252a6c00660'}
         ValueOrQuoteTransfer{id=1, name='abbdf6af-ee4a-4013-a541-a40351af5001'}
         ValueOrQuoteTransfer{id=1, name='abbdf6af-ee4a-4013-a541-a40351af5001'}
         ValueOrQuoteTransfer{id=1, name='f150d849-5313-476d-bae9-b4ea77e60601'}
         ValueOrQuoteTransfer{id=1, name='f150d849-5313-476d-bae9-b4ea77e60601'}
         ValueOrQuoteTransfer{id=1, name='6b76e3f3-785c-4893-a8c8-969fe613ec81'}
         ValueOrQuoteTransfer{id=1, name='6b76e3f3-785c-4893-a8c8-969fe613ec81'}
         ValueOrQuoteTransfer{id=1, name='499c4ce7-9333-4ba1-8f73-e1125c4e3957'}
         ValueOrQuoteTransfer{id=1, name='499c4ce7-9333-4ba1-8f73-e1125c4e3957'}
         ValueOrQuoteTransfer{id=1, name='c0fc60cd-2190-4777-a892-9fbd37b98c80'}
         ValueOrQuoteTransfer{id=1, name='c0fc60cd-2190-4777-a892-9fbd37b98c80'}
         ValueOrQuoteTransfer{id=1, name='e9bf9acb-d494-40af-a1ca-f1e313afcbf5'}
         ValueOrQuoteTransfer{id=1, name='e9bf9acb-d494-40af-a1ca-f1e313afcbf5'}
         ValueOrQuoteTransfer{id=1, name='56e281fc-7cd2-493f-85f1-6f937ca836dc'}
         ValueOrQuoteTransfer{id=1, name='56e281fc-7cd2-493f-85f1-6f937ca836dc'}



你可能感兴趣的:(java,线程,对象,值传递,引用传递)