0

0

Java陷阱之assert关键字详解

高洛峰

高洛峰

发布时间:2017-01-16 16:04:11

|

2336人浏览过

|

来源于php中文网

原创

一、概述
 
在c和c++语言中都有assert关键,表示断言。
在java中,同样也有assert关键字,表示断言,用法和含义都差不多。

二、语法
 
在java中,assert关键字是从java se 1.4 引入的,为了避免和老版本的java代码中使用了assert关键字导致错误,java在执行的时候默认是不启动断言检查的(这个时候,所有的断言语句都 将忽略!),如果要开启断言检查,则需要用开关-enableassertions或-ea来开启。

assert关键字语法很简单,有两种用法:

1、assert
如果为true,则程序继续执行。
如果为false,则程序抛出assertionerror,并终止执行。

2、assert :
如果为true,则程序继续执行。
如果为false,则程序抛出java.lang.assertionerror,并输入。

三、应用实例
 
下面给出一个例子,通过例子说明其用法:

public class AssertFoo {
    public static void main(String args[]) {
        //断言1结果为true,则继续往下执行
        assert true;
        System.out.println("断言1没有问题,Go!");

        System.out.println("\n-----------------\n");

        //断言2结果为false,程序终止
        assert false : "断言失败,此表达式的信息将会在抛出异常的时候输出!";
        System.out.println("断言2没有问题,Go!");
    }
}

保存代码到C:\AssertFoo.java,然后按照下面的方式执行,查看控制台输出结果:

1、编译程序:
C:\>javac AssertFoo.java

2、默认执行程序,没有开启-ea开关:
C:\>java AssertFoo
断言1没有问题,Go!

-----------------

断言2没有问题,Go!

3、开启-ea开关,执行程序:
C:\>java -ea AssertFoo
断言1没有问题,Go!

-----------------

Exception in thread "main" java.lang.AssertionError: 断言失败,此表达式的信息将
会在抛出异常的时候输出!
        at AssertFoo.main(AssertFoo.java:10)

四、陷阱
 
assert关键字用法简单,但是使用assert往往会让你陷入越来越深的陷阱中。应避免使用。笔者经过研究,总结了以下原因:

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

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

3、assert断言失败将面临程序的退出。这在一个生产环境下的应用是绝不能容忍的。一般都是通过异常处理来解决程序中潜在的错误。但是使用断言就很危险,一旦失败系统就挂了。

 
五、对assert的思考
 
assert既然是为了调试测试程序用,不在正式生产环境下用,那应该考虑更好的测试JUint来代替其做用,JUint相对assert关键的所提供的功能是有过之而无不及。当然完全可以通过IDE debug来进行调试测试。在此看来,assert的前途一片昏暗。

因此,应当避免在Java中使用assert关键字,除非哪一天Java默认支持开启-ea的开关,这时候可以考虑。对比一下,assert能给你带来多少好处,多少麻烦,这是我们选择是否使用的的原则。

============================================================
comment:
反过来说,在某些开源组件中,比如validator、junit中,判断过程仿佛使用了断言风格,很有可能使用了大量的断言,但笔者在没看源码之前不能确定。
如果是开发阶段的简单测试,junit就是一个便捷强悍的工具,没有理由自己写断言而不去用它。

============================================================
comment:
首先可以用在单元测试代码中。junit侵入性是很强的,如果整个工程大量的代码都使用了junit,就难以去掉或者是选择另外一个框架。如果单元测试代码 很多,并且想复用这些单元测试案例,应该选择assert而不是junit,便于使用别的单元测试框架,比如TestNG。同理正式的功能代码根本就不应 该出现Junit,应该使用assert.

assert主要适合在基类,框架类,接口类,核心代码类,工具类中。换言之,当你的代码的调用者是另外一个程序员写得业务代码,或者是另外一个子系统时,就很有必要使用它。比如你做了一个快速排序的算法

public static List<int> quickSort(List<int> list){
  assert list != null;
  // 申请临时空间
  //开始排序
  for(int i : list){
      //
  }
}

这种情况下,如果不检查传入参数的正确性,会抛出一个莫名其妙的空指针错误。你的调用者可能并不清楚你代码的细节,在一个系统的深处调试一个空指针错误是很浪费时间的。就应该直接明确的告诉你的调用者是传入的参数有问题。否则他会怀疑你的代码有BUG。使用assert可以避免两个程序员之间互相指责对方写的代码有问题。

assert适用那些你知道具体是什么错误,你和你的调用者已经约定应该由你的调用者去排除或检查的错误。你通过一个断言告诉你的调用者。assert不适用那些外部系统造成的错误,比如用户输入数据的错误,某个外部文件格式错误。这些错误不是你的调用者而是用户造成的,甚至于不属于异常,因为出现输入错误和文件格式错误是经常的,这些错误应该由业务代码去检查。

assert比较适合于被频繁调用的 基类,框架代码,工具类,核心代码,接口代码中,这正是它在运行时被去掉的原因。测试代码应该在测试阶段开启-ea参数,便于对系统深处的核心代码做仔细的测试。

立即学习Java免费学习笔记(深入)”;

秘塔AI搜索
秘塔AI搜索

秘塔AI搜索,没有广告,直达结果

下载

Java较少使用assert的原因是Java有很完整的OO体系,强制类型转换出现得较少,所以不需要类似c那样需要频繁的检查指针的类型是否正确,指针是否为空。同时Java也很少直接管理内存或缓冲区,所以不需要频繁的检查传入的缓冲区是否为空或者是已经越界。

但使用好assert有助于提高框架代码的正确性和减少框架代码的使用者的调试时间。

===============================================================
comment:
assert要达到的目的是让程序员方便的发现自己的逻辑错误,并且不影响程序的效率。assert所发现的错误,是完全不应该出现的,是不能用异常代替的。异常,那是系统所允许的,或者是系统不可控的“错误”,它不是程序员的逻辑问题。

assert应该是开发阶段打开,而在发布后关闭。

更多Java陷阱之assert关键字详解相关文章请关注PHP中文网!

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

286

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

126

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

42

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

19

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

23

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

29

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

14

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

421

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

51

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号