新手常犯技术问题
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
由于类中的方法都可以修改类变量的值,那么使用类变量来解决函数间的数据共享问题就会出现可能的错误。
所以,要减少或避免使用类变量来解决问题,应该考虑用传递参数、函数返回值的办法。
1.2
不给局部变量赋初值不管是C#还是Java都会给类成员变量自动赋初值,但不会给局部变量赋初值,所以,如果要得到正确的结果,一定要给局部变量赋初值。
注:如果不给局部变量赋初值,Java编译器会报错。但不是所有的编译器都报错。
很多情况下,对返回值的判断决定程序下一步是否进行。所以,一定要注意返回值的判断。
方法methodA已经给出了系统错误的情况,但由于没有对其返回值进行判断,导致程序最终给出了错误的结论。
public void printSystemState() { methodA(); methodB(); System.out.println("System is normal."); }
private boolean methodA() { System.out.println("System error."); return false; }
private void methodB() { } |
该例中方法methodB会抛出NullPointerException,是由于没有对methodA的返回值进行有效性判断。
public void judgeString() { final String str = methodA(); methodB(str); }
private String methodA() { return null; }
private void methodB(String str) { if(str.equals("test")) { System.out.println("The string input is test."); } } |
变量或函数的命名要符合变量或函数所代表的意义,直观的讲,就是让读者一看就知道变量或者函数的用途。
如果字符串和一个常量字符串进行比较,常量字符串应该放在前面。如果两个非常量字符串进行比较,要确认前面的字符串不是null.
如下的代码则会抛出NullPointerException类型的异常。
private void methodB(String str) { if(str.equals("test")) { System.out.println("The string input is test."); } <?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><shape id="_x0000_s1027" style="MARGIN-TOP: 1.55pt; Z-INDEX: 2; MARGIN-LEFT: 221.4pt; WIDTH: 36pt; POSITION: absolute; HEIGHT: 27pt" strokecolor="green" fillcolor="blue" type="#_x0000_t67"><textbox style="LAYOUT-FLOW: vertical-ideographic"></textbox></shape>} |
private void methodB(String str) { if("test".equals(str)) { System.out.println("The string input is test."); } } |
常常一个方法的实现没有一行注释,开发者在编写的时候应该在一些关键步骤添加必要的解释,以方便读者的阅读和理解,同时对开发者本身来讲,将来修改代码的时候也容易记起当时的想法。
常常听开发者讲,这个方法我测了几遍,没有问题。这个方法的实现果真没有问题吗?
开发者本身的测试常常会集中在正常流程的情况下,而对于一些边界情况、异常情况则很少在意。再者,这种随机的测试也不能保证正确性。
代码的正确首先要从设计、逻辑这方面保证,然后在通过严格的测试来保证代码的正确性。
当然,有些运行很稳定的代码不一定就是正确的,只是现有的情况还没有命中代码的缺陷。
虽然一些高级语言,例如C#,Java都会对内存进行管理,开发者不用担心内存操作的复杂性,但是对于文件的操作却都没有提供安全的管理。
也就是说,文件的操作一定要开发者自己来处理,打开的文件一定要自己关闭。
对于Java来讲,可以通过Findbugs来发现文件操作潜在的问题。
下边这个例子就没有成功的关闭文件。一旦在inStream读取的时候发生异常,两个打开的文件都不能正确的关闭。这时候可以考虑使用finally来关闭文件。
public boolean copyFile(String srcPath, String destPath) { boolean result = false;
// check source whether exist final File oldfile = new File(srcPath); if (!oldfile.exists()) { return result; }
InputStream inStream = null; OutputStream outStream = null; try { inStream = new FileInputStream(srcPath); outStream = new FileOutputStream(destPath); final byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = inStream.read(buffer)) != -1) { outStream.write(buffer, 0, bytesRead); }
inStream.close(); outStream.close();
result = true; } catch (IOException e) { }
return result; <shape id="_x0000_s1028" style="MARGIN-TOP: 1.95pt; Z-INDEX: 3; MARGIN-LEFT: 324.55pt; WIDTH: 36pt; POSITION: absolute; HEIGHT: 27pt" strokecolor="green" fillcolor="blue" type="#_x0000_t67"><textbox style="LAYOUT-FLOW: vertical-ideographic"></textbox></shape>} |
public boolean copyFile(String srcPath, String destPath) { boolean result = false;
// check source whether exist ……
InputStream inStream = null; OutputStream outStream = null; try { …… result = true; } catch (IOException e) { } finally { try { if (null != inStream) { inStream.close(); } if (null != outStream) { outStream.close(); } } catch (IOException e) { } } return result; } |
曾经见过六层if嵌套的代码,试想这样的代码看起来有多费劲。所以,要减少嵌套过深的代码。
private String methodA() { if (a) { if (b) { if (c) { if (d) { System.out.println("abcd"); } } } } <shape id="_x0000_s1029" style="MARGIN-TOP: 5.85pt; Z-INDEX: 4; MARGIN-LEFT: 212.4pt; WIDTH: 36pt; POSITION: absolute; HEIGHT: 27pt" strokecolor="green" fillcolor="blue" type="#_x0000_t67"><textbox style="LAYOUT-FLOW: vertical-ideographic"></textbox></shape>} |
private String methodA() { if (a && b && c && d) { System.out.println("abcd"); } } |
往往测试代码的要求在于测试覆盖率要达到多少,而没有assert语句的测试代码对于覆盖率没有任何影响,但assert语句却对测试代码有很重要的作用,它反应测试代码的正确性。
例如有如下方法,返回字符串test。
private String methodA() { return "test"; } |
该测试方法虽然调用了methodA方法,测试覆盖率也100%,但却没有验证methodA的正确性。
public void testMethodA() { methodA(); } |
使用assert来验证方法的返回值。
public void testMethodA() { String str = methodA(); assertEquals(str, "test"); } |
在测试代码中,经常会有一些为了测试建立的文件夹或文件,如果不注意删除。那么就可能在测试者机器上出现无用的文件夹或文件。
在测试代码中要注意清理这些无用的东西。
public void testMethodA() { final String outputDir = "./main/test/out/"; FileOperator.createFolder(outputDir); // create folder for test …… // test code FileOperator.deleteFiles(outputDir); // delete test folder } |