`

Java函数中的参数有效性检查

 
阅读更多

在Java程序中,方法与属性是类中最基本的成员。下面的问题与方法有关:

实现一个方法的第一步是什么?

说到这里我突然想起侯耀文、赵丽蓉两位艺术家在小品《英雄母亲的一天》中有这样一段台词:

导演:您起床后做的第一件事是什么?可以随便说。
大娘一听可以随便说,笑了。
大娘(凑到导演的耳朵边,轻声地):上厕所。

在这里,我也想做一回导演,把上面的台词改一下:

编程新手:您在实现类中的一个方法时,第一步要做的事是什么?可以随便说。
编程老手一听可以随便说,笑了。
编程老手(凑到新手的耳朵边,轻声地):参数有效性检查。

大娘的回答铁定不是导演希望听到的,编程老手的回答恐怕也不是新手想要得到的。原因很简单,与正题无关。但是参数有效性检查之于方法实现的重要性决不亚于早上起来上厕所,个中原因只可意会,不可言传。这里要讨论的是如何在Java中进行参数有效性检查。

说到参数有效性检查,不得不说一下运行时异常。Java有两种异常:一般异常与运行时异常。继承自Exception的异常称为一般异常,继承自RuntimeException的异常称为运行时异常。与一般异常最大的不同之处在于,函数调用方可以不必处理实现方抛出的运行时异常。 但是异常的抛出通常会被当成一种错误的发生。如果调用方可以不用处理运行时异常,那就意味着调用方必须尽量避免实现方抛出运行时异常。 例如:

[java] view plain copy
 
  1. public static boolean equalObject(Object obj1, Object obj2) {  
  2.     return obj1.equals(obj2);  
  3. }  

 

上述代码在obj1为null的场合下会抛出NullPointerException,为了避免这种情况发生,正确的写法应该是:

 

[java] view plain copy
 
  1. public static boolean equalObject(Object obj1, Object obj2) {  
  2.     return (obj1 != null && obj1.equals(obj2));  
  3. }  



可以看出,运行时异常是对函数调用方一种无形的约束,这种约束方式正好符合参数有效性检查的要求,即调用方法时必须提供正确的参数,否则就会导致系统崩溃。例如我们通过物体的质量计算其重力值。实现方法如下:

 

 

[java] view plain copy
 
  1. public class Test {  
  2.     public static void main(String[] args) {  
  3.         System.out.println(getGravity(1.0));  
  4.     }  
  5.   
  6.     public static double getGravity(double mass) {  
  7.         return mass * 9.82;  
  8.     }  
  9. }  

 

 

我们知道一般情况下一个1.0千克的物体其重力为9.82牛顿,但质量为负数的物体呢?物理常识告诉我们,世界上不存在质量为0或小于0的物体,据此我们应该如何完善重力的计算方法呢?

计算重力的第一步应该是对质量进行参数有效性检查。Java SDK中提供了许多种运行时异常,与参数有效性检查相关的异常是IllegalArgumentException。代码实现可以如下:

 

[java] view plain copy
 
  1. public static double getGravity(double mass) {  
  2.     // 参数有效性检查  
  3.     if (mass <= 0) {  
  4.         throw new IllegalArgumentException("无效质量:" + mass);  
  5.     }  
  6.   
  7.     return mass * 9.82;  
  8. }  

 

 

当我们调用这样一个计算重力的方法时,应该尽量传递有效的质量值。当我们传递一个负值给此方法时,系统将会以抛出异常的方式退出。如:

[java] view plain copy
 
  1. public class Test {  
  2.     public static void main(String[] args) {  
  3.   
  4.         System.out.println(getGravity(1.0)); // 有效的质量  
  5.         // 我们应该尽量避免下面的调用  
  6.         // System.out.println(getGravity(-1.0)); // 无效的质量  
  7.     }  
  8.   
  9.     public static double getGravity(double mass) {  
  10.   
  11.         // 参数有效性检查  
  12.         if (mass <= 0) {  
  13.             throw new IllegalArgumentException("无效质量:" + mass);  
  14.         }  
  15.   
  16.         return mass * 9.82;  
  17.     }  
  18. }  

 

参数有效性检查应该作为常识来掌握,特别是Java中特有的参数有效性检查。上面介绍的是最基本的用法,当然我们也可以利用第三方程序库(如Apache Commons Lang 库的Validate类)来简化参数有效性检查的过程。

 

 

每当编写方法或者构造器的时候,应该考虑他的参数有哪些限制。应该把这些限制写到文档中,并且在这个方法体的开头处,通过显式的检查来实施这些限制。养成这样的习惯是非常重要的。
demo:
1\对于公有的方法,要用Javadoc的@throws标签(tag)在文档中说明违反参数值限制会抛出异常。
手工抛出异常,并且添加@throws注解说明原因

 

[java] view plain copy
 
  1. /** 
  2.  * hello..... 
  3.  * @param m 
  4.  * @return 
  5.  * @throws NullPointerException if m is null 
  6.  * @throws ArithmeticException if m is less than or equals to 0 
  7.  */  
  8. public BigInteger mod(BigInteger m) {  
  9.     if(m == null){  
  10.         throw new NullPointerException("m is null:" + m);  
  11.     }  
  12.     if (m.signum() <= 0) {  
  13.         throw new ArithmeticException("Modulus <= 0: " + m);  
  14.     }  
  15.     // Do something  
  16.     return null;  
  17. }  


2\对于未被导出的方法(unexported method),作为包的创建者,你可以控制这个方法将在哪些情况下被使用,因此你可以,也应该确保只将有效的参数传递进来。
因此,非公有的方法通常应该使用断言(assertion)来检查他们的参数。
通过将-ea(或者-enableassertions)标记传递给java解释器,来启动他们。 
(一般来说 assert 在开发的时候是检查程序的安全性的,在发布的时候通常都不使用 assert 。)

 

 

[java] view plain copy
 
  1. /** 
  2.  *  
  3.  * @param a 
  4.  * @param offset 
  5.  * @param length 
  6.  */  
  7. private static void sort(long[] a,int offset,int length){  
  8.     assert a != null;  
  9.     assert offset >= 0 && offset <= a.length;  
  10.     System.out.println("sort do something");  
  11. }  


不同于junit里的断言方法:

 

 

[java] view plain copy
 
  1. private static void sort2(long[] a, int offset, int length) {  
  2.     Assert.assertTrue("a is null", a != null);  
  3.     Assert.assertTrue(offset >= 0 && offset <= a.length);  
  4.     System.out.println("sort do something");  
  5. }  

 

 

分享到:
评论

相关推荐

    java 请求参数过滤拦截

    在Java开发中,请求参数过滤拦截是一个至关重要的环节,它涉及到系统的安全性、稳定性和数据的正确性。这里的“java请求参数过滤拦截”主要是指在接口接收到用户输入的数据时,通过过滤器(Filter)对参数进行检查,...

    伽玛函数数值解法Java代码

    此外,可能还包含了一些错误检查和异常处理机制,以确保输入的有效性。 7. **测试与验证**: 最后,代码应该包含测试用例,验证计算结果的正确性。这可能包括已知伽玛函数值的点,以及一些特殊点(如x=1/2, x=1, x=2...

    Java计算机语言函数应用(PDG)

    // 这里进行输入处理,如检查有效性、转换等 return processedInput; } %&gt; 示例JSP页面 提交" /&gt; ``` 在上述代码中,`processInput`函数接收用户输入并进行处理,然后可以在其他地方调用这个函数...

    Java泛型构造函数(学习资料)

    Java 泛型构造函数是Java编程中用于增强类型安全性的工具,它们允许我们在类的构造函数中使用类型参数。在创建对象时,泛型构造函数能够确保传入的数据类型符合预定义的约束,从而减少类型转换错误并提高代码的...

    java接口 参数MD5加密.zip

    在接口调用中,参数的合法性检查是必不可少的,防止因错误的输入导致程序异常。Tools类可能包含一系列静态方法,用于验证输入参数的类型、格式、范围等。例如,检查字符串非空、数字有效性、日期格式等。此外,还...

    JAVA验证URL是否有效连接的方法

    通过以上介绍,我们了解了如何使用Java编程语言中的`HttpURLConnection`类来检测URL的有效性。这种方法简单易用,同时具备一定的健壮性和灵活性,适用于多种应用场景。希望本文能够帮助大家解决类似问题,提高开发...

    Java中使用Preconditions来检查传入参数介绍

    此外,由于`Preconditions`的方法不会在发布版本中被优化掉,因此即使在生产环境中,也能保证参数检查的有效性,这对于维护高质量的代码是十分必要的。 总之,`Preconditions`是Java开发中一种有效的工具,它可以...

    JAVA字符串处理函数列表一览

    ### JAVA字符串处理函数列表一览 在Java编程语言中,字符串处理是极其常见且重要的操作之一。字符串类`String`提供了丰富的内置方法来帮助开发者高效地完成各种字符串操作任务。本文将详细解读`String`类中的一些...

    java链接postgresql

    如果遇到问题,可以检查数据库配置是否正确,JDBC驱动是否已添加,以及SQL语句是否有效。 综上所述,"java链接postgresql"涉及到的关键技术包括JDBC接口的使用、PostgreSQL JDBC驱动的集成、数据库连接的建立与关闭...

    oracle调用java包

    在Oracle数据库系统中,有时我们需要将Java代码集成到PL/SQL程序中,以便利用Java的强大功能,例如处理复杂的算法、大数据操作或者与外部系统...了解这些知识点有助于我们更有效地在Oracle环境中集成和使用Java代码。

    Java 什么是函数式编程.pdf

    在Java 8中,为了引入函数式编程,引入了Lambda表达式和Stream API,极大地提升了代码的简洁性和可读性。 Lambda表达式是Java 8的一个核心特性,它允许我们以更简洁的方式定义匿名函数。传统的函数定义通常需要一个...

    编写函数DM

    在IT行业中,编写函数是编程工作中的基础环节,无论是在脚本语言如Python,还是在编译型语言如C++或Java中,函数都扮演着至关重要的角色。函数是代码组织的基本单元,它封装了一段特定功能的逻辑,使得代码更易于...

    day12【函数式接口】-笔记1

    在Java中,Lambda表达式是函数式编程的核心,它可以被理解为没有名字的、一次性使用的、轻量级的函数。由于Lambda表达式的存在,我们可以更简洁地处理那些只需要一次实现的简单功能,而无需创建完整的类。 1.2 格式...

    Java开发技术大全(500个源代码).

    realExample.java 演示浮点数的有效位数 remainder.java 取余运算示例 showBreak.java 利用标号语句跳转出所有循环嵌套 showCount.java 循环计数示例 showDoubleLoop.java 演示双重循环 showDoubleLoopSe.java...

    计算机软件-编程源码-Java计算机语言函数应用.zip

    源码中可能会展示如何有效地利用异常处理来增强程序的健壮性。 5. **数组与集合框架**:Java提供了一整套的集合框架,如ArrayList、LinkedList、HashMap等,源码可以展示如何创建和操作这些数据结构,以及它们在...

    java+OpenCV 图片对比、标记差异部分(可以支持中文路径)

    Java结合OpenCV库,能够有效地实现复杂的图像操作,比如图片对比和标记差异部分。本篇将深入探讨如何利用Java和OpenCV进行图片对比,并且支持中文路径。 首先,OpenCV是一个强大的开源计算机视觉库,它提供了丰富的...

    Oracle中的函数、存储过程、包

    - **包**是封装相关函数和过程的容器,类似于Java中的接口,提供了一种组织和命名空间管理的方法。 - **包头(Specification)**:定义包的接口,包括函数和过程的签名,不包含实现细节。 - **包体(Body)**:...

    LR中使用Java Vuser测试Java类功能

    通过以上步骤,我们可以使用LR中的Java Vuser有效地测试Java类的功能,确保应用程序在高负载下的稳定性和性能。在实际测试过程中,还需要结合具体的业务逻辑和应用环境,进行定制化的测试脚本编写和场景设计。 至于...

Global site tag (gtag.js) - Google Analytics