关于java:JAVA中的断言是什么有什么陷阱

如何在 Java 中应用断言

什么是 Java 断言?

在 JDK 1.4之前,开发人员常常应用正文来记录对于程序正确性的假如。然而,正文作为测试和调试假如的机制是无用的。编译器疏忽正文,因而无奈应用它们进行 bug 检测。开发人员在更改代码时也常常不更新正文。

在 JDK 1.4中,断言被引入作为测试和调试代码假如的新机制。本质上,断言是在运行时执行的可编译实体,假如你曾经为程序测试启用了它们。能够通过编写断言来告诉 bug 产生的中央,这样能够大大减少调试失败程序的工夫。

如何用 Java 编写断言

编写断言的表达式:

assert BooleanExpr;

如果 BooleanExpr 的计算结果为 true,则不会产生任何事件,并继续执行。然而,如果表达式计算结果为 false,那么将抛出 AssertionError

举个例子

    public static void main(String[] args) {
        int a = 10;
        assert a>100;//false
    }

此断言表明开发人员认为变量 a 蕴含一个大于100的值。然而,状况显然不是这样;

assert 语句的执行导致抛出 AssertionError

运行后没有反馈??

有的小伙伴发现自己的IDE并没有抛出Error 这是因为没有显示开启,启用断言
开启办法: vm options 退出 -ea

此时咱们运行我的项目 发现抛出了异样

Exception in thread "main" java.lang.AssertionError
    at Scratch.main(scratch_4.java:4)

心愿取得更多信息?

此时咱们曾经晓得了断言的根本用法 然而抛出Error后咱们并不知道是什么问题导致的 还须要去翻看代码找到报错的中央, 如果咱们心愿取得更多有用的信息 咱们能够这样批改Assert语句:

assert BooleanExpr : expr;

expr 是任何能够返回值的表达式(包含办法调用)然而不能调用具备 void 返回类型的办法。一个有用的表达式是一个字符串,用它来形容失败的起因

举个例子

public static void main(String[] args) {
        int a = 10;
        assert a>100 : "a < 100"; 
    }

运行:

Exception in thread "main" java.lang.AssertionError: a < 100
    at Scratch.main(scratch_4.java:5)

无论哪个例子,在不应用-ea (启用断言)选项的状况下运行都不会产生输入。当断言未启用时,它们不会执行,只管它们依然存在于类文件中。

前置条件和后置条件

前置条件: 是在执行某些代码之前必须求值为 true 的条件

后置条件: 是在执行某些代码后必须求值为 true 的条件

前置条件

前置条件查看:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

class PNG
    {
        /**
         *  Create a PNG instance, read specified PNG file, and decode
         *  it into suitable structures.
         *
         *  @param filespec path and name of PNG file to read
         *
         *  @throws NullPointerException when <code>filespec</code> is
         *          <code>null</code>
         */
        PNG(String filespec) throws IOException
        {
            //在非公有构造方法中 应用前置条件
            if (filespec == null)
                throw new NullPointerException("filespec is null");
            try (FileInputStream fis = new FileInputStream(filespec))
            {
                readHeader(fis);
            }
        }

        private void readHeader(InputStream is) throws IOException
        {  
                //在公有办法中应用前置条件查看
            assert is != null : "null passed to is";
        }
    }

    class Scratch
    {
        public static void main(String[] args) throws IOException
        {
            PNG png = new PNG((args.length == 0) ? null : args[0]);
        }
    }

后置条件

后置条件查看:

public class AssertDemo
{
   public static void main(String[] args)
   {
      int[] array = { 20, 91, -6, 16, 0, 7, 51, 42, 3, 1 };
      sort(array);
      for (int element: array)
         System.out.printf("%d ", element);
      System.out.println();
   }

   private static boolean isSorted(int[] x)
   {
      for (int i = 0; i < x.length - 1; i++)
         if (x[i] > x[i + 1])
            return false;
      return true;
   }

   private static void sort(int[] x)
   {
      int j, a;
      // For all integer values except the leftmost value ...
      for (int i = 1; i < x.length; i++)
      {
         // Get integer value a.
         a = x[i];
         // Get index of a. This is the initial insert position, which is
         // used if a is larger than all values in the sorted section.
         j = i;
         // While values exist to the left of a's insert position and the
         // value immediately to the left of that insert position is
         // numerically greater than a's value ...
         while (j > 0 && x[j - 1] > a)
         {
            // Shift left value -- x[j - 1] -- one position to its right --
            // x[j].
            x[j] = x[j - 1];
            // Update insert position to shifted value's original position
            // (one position to the left).
            j--;
         }
         // Insert a at insert position (which is either the initial insert
         // position or the final insert position), where a is greater than
         // or equal to all values to its left.
         x[j] = a;
      }
      //在 sort ()返回给它的调用者之前,我应用 assert 查看 x 被排序的后置条件。
      assert isSorted(x): "array not sorted";
   }
}

陷阱

assert关键字用法简略,然而应用assert往往会让你陷入越来越深的陷阱中。应防止应用。笔者通过钻研,总结了以下起因:

1、 assert关键字须要在运行时候显式开启能力失效,否则你的断言就没有任何意义。而当初支流的Java IDE工具默认都没有开启-ea断言查看性能。这就意味着你如果应用IDE工具编码,调试运行时候会有肯定的麻烦。并且,对于Java Web利用,程序代码都是部署在容器外面,你没法间接去控制程序的运行,如果肯定要开启-ea的开关,则须要更改Web容器的运行配置参数。这对程序的移 植和部署都带来很大的不便。

2、用assert代替if是陷阱之二。assert的判断和if语句差不多,但两者的作用有着实质的区别:assert关键字本意上是为测试 调试程序时应用的,但如果不小心用assert来管制了程序的业务流程,那在测试调试完结后去掉assert关键字就意味着批改了程序的失常的逻辑。

3、assert断言失败将面临程序的退出。这在一个生产环境下的利用是绝不能容忍的。个别都是通过异样解决来解决程序中潜在的谬误。然而应用断言就很危险,一旦失败零碎就挂了。

总结

assert既然是为了调试测试程序用,不在正式生产环境下用,那应该思考更好的测试JUint来代替其做用,JUint绝对assert要害的所提供的性能是有过之而无不及。当然齐全能够通过IDE debug来进行调试测试

因而,该当防止在Java中应用assert关键字,除非哪一天Java默认反对开启-ea的开关,这时候能够思考。比照一下,assert能给你带来多少益处,多少麻烦,这是咱们抉择是否应用的的准则,读者能够自行取舍.

关注公众号:java宝典

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理