问题引出:
从刚接触代码就被灌输这样的思想:
1. 你写的代码不是没有错误,而是至今还没有发现错误。
2. 测试是为了发现错误,而不是为了确定软件没有错误。
3. 写的代码一定要有很高的健壮性。
但是,你看一下下面的代码,你觉得这个代码的健壮性如何?
public class Test{ public static void main(String[] args) throws InterruptedException{ final int[] denominators={1,2,3}; new Thread(new Runnable() { @Override public void run() { try { Divide100By(denominators); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); Thread.sleep(50); denominators[2]=0; } private static void Divide100By(Object o) throws InterruptedException{ int[] denominators=(int[]) o; for(int i=0;i<denominators.length;i++){ if(denominators[i]==0){ throw new RuntimeException("除数不能为0"); } } System.out.println("所有的除数都合法"); Thread.sleep(100); for(int i=0;i<denominators.length;i++){ //System.out.println(""+denominators[i]); System.out.println("100/"+denominators[i]+"="+100/denominators[i]); } } }
问题分析
依我看,上面的Divide100这个方法,是一个不错的代码,因为他对传过来的数组进行了是否为0的判断。
在这里引入一条:对方法的参数,需要进行有效性判断。因为方法执行正确比方法执行错误的执行效率要高很多。
而在我执行上面代码的时候,却意外的发现有错。这是怎么回事呢?
原来在传递参数的时候,如果是值类型,会采取传值的方式进行传递,如果是对象,那么就会传引用。关于传值和传引用的具体区别,大家可以看一下这篇博客:http://blog.csdn.net/hanxuemin12345/article/details/10470955
大概意思就是传引用形参和实参会相互影响,传值互不影响。
正是由于这点的存在,让这个看似健壮的方法产生了错误。
问题总结
解决方法其实很简单,在将形参转型后,再声明一个一模一样的数组,然后把转好的数组复制给新的数组,剩下的所有操作都对这个新数组操作就可以摆脱这个问题了。
其实如果不是要写成一个类库,如果不采用多线程,如果你不知道传引用和传值的区别,一切都没那么麻烦。但我们要做的不是这样的人。
通过这个例子,又一次体会了“不是没有错,而是暂时还没有发现错”这句话。也希望大家受到这个的启发,在开发的时候,尽量使自己写的代码能够正确被调用。