《编写高质量代码 改善Java程序的151个建议》书摘

例子1:三元操作符的陷阱
1 int i = 80;
2 String str1 = String.valueOf(i < 100 ? 90 : 100);
3 String str2 = String.valueOf(i < 100 ? 90 : 100.0);
4 System.out.println(str1);// 输出:90
5 System.out.println(str2);// 输出:90.0
当你使用三元运算符,两边的操作数的类型不一致的时候,这就涉及到三元操作符的转换规则:
  1. 若两个操作数不可转换,则不做转换,返回值为Object类型;
  2. 若两个操作数是明确类型的表达式(比如变量),则按照正常的二进制数字来转换。int类型转换为long类型,long类型转换成float类型;
  3. 若两个操作数中有一个是数字S,另外一个是表达式,且其类型为T,那么,若数字S在T的范围内,则转换为T类型;若S超过了T的范围,则T转换为S类型;
  4. 若两个操作数字都是数字。则返回值类型为范围较大者。


例子2:一个关于自增的陷阱

1 int count = 0;
2 for(int i=0; i<=100; i++) {
3     count = count++;
4 }
5 System.out.println("count = " + count);//输出:count = 0

循环体内的“count = count++;”语句第一次执行时的详细处理步骤如下:

  1. JVM把count值(此时为0)拷贝到临时变量区;
  2. 将count的值加1(此时为1);
  3. 返回临时变量区的值(此时为0);
  4. 将返回值赋值给count(即count被赋值为0)。

用代码来表示则相当于以下语句:

1 public static int mockAdd(int count) {
2     int temp = count;
3     count = count + 1;
4     return temp;
5 }

不过,在C++中,“count = count++”与“count++”是等效的,PHP与Java则一样(不等效)


例子3:如何结合JS脚本处理易变的业务
1 //JS代码
2 var factor;
3 function formula(var1, var2) {
4     return var1 + var2 * factor;
5 }
 1 //Java代码
 2 int first = 11;
 3 int second = 22;
 4 String filePath = "D:/test.js";
 5 ScriptEngineManager manager = new ScriptEngineManager();
 6 // 获得一个javascript的执行引擎
 7 ScriptEngine engine = manager.getEngineByName("javascript");
 8 // 建立上下文变量
 9 Bindings bind = engine.createBindings();
10 // 为js文件里的某个参数赋值
11 bind.put("factor", 5);
12 // 绑定上下文,作用域是当前引擎范围
13 engine.setBindings(bind, ScriptContext.ENGINE_SCOPE);
14 FileReader fr = new FileReader(filePath);
15 engine.eval(fr);// 执行js代码
16 // 判断是否为可调用的方法
17 if (engine instanceof Invocable) {
18     Invocable invocable = (Invocable) engine;
19     Double result = (Double) invocable.invokeFunction("formula", first,
20             second);
21     System.out.println("运算结果: " + result.intValue());
22 }

例子5:关于instanceof方法的使用
 1 import java.util.Date;
 2
 3 public class InstanceofDemo {
 4     public static void main(String[] args) {
 5         System.out.println("Sting" instanceof Object);// 输出:true
 6         // 分析:“String"是一个字符串,字符串又继承了Object
 7         /***********************************/
 8
 9         System.out.println(new String() instanceof String);// 输出:true
10         // 分析:一个类的对象当然是它的实例
11         /***********************************/
12
13         System.out.println(new Object() instanceof String);// 输出:false
14         // 分析:Object是父类,其对象当然不是String类的实例了。
15         // 需要注意的是,这语句编译通过了,因为只要instanceof关键字的左右两个操作数有继承或实现关系,就可以编译通过
16         /***********************************/
17
18         System.out.println(null instanceof String);// 输出:false
19         // 分析:instanceof特有的规则:若左操作数是null,结果就直接返回false,不需要判断运算右操作数是什么类,类似短路运算。
20         // 因此,在使用instanceof操作符时,不用关心被判断的类(也就是左操作数)是否为null,这与我们经常用到的equals、toString方法不同。
21         /***********************************/
22
23         System.out.println((String) null instanceof String);// 输出:false
24         // 分析:不要看这里有个强制类型转换就认为结果是true。因为null是一个万用类型,也可以说它没类型,即使进行类型转换还是个null
25         /***********************************/
26
27         System.out.println(‘A‘ instanceof Character);// 编译报错
28         // 分析:
29         // 因为‘A‘是一个char类型,也就是一个基本类型,不是一个对象,instanceof只能用于对象的判断,不能用于基本类型的判断,所以编译报错
30         /***********************************/
31
32         System.out.println(new Date() instanceof String);// 编译报错
33         // 分析:因为Date类与String没有继承或实现关系,所以在编译时直接就报错了,instanceof操作符的左右操作数必须有继承或实现关系,否则会编译不通过
34         /***********************************/
35
36         System.out.println(new GenericClass<String>().isDateInstance("test"));// 输出:false
37         // 分析:此处T是个String类型,与Date之间没有继承或实现关系,为什么语句"return t instanceof Date"会编译通过呢?
38         // 因为Java的泛型是为编码服务的,在编译成字节码时,T已经是Object类型了,传递的实参是String类型,也就是说T的表面类型是Object,实际类型是String
39         // 所以,语句此处的"return t instanceof Date"语句就等价于"return Object instanceof Date"了
40     }
41 }
42
43 class GenericClass<T> {
44     // 判断是否是Date类型
45     public boolean isDateInstance(T t) {
46         return t instanceof Date;
47     }
48 }
 
 
时间: 2024-12-07 04:21:17

《编写高质量代码 改善Java程序的151个建议》书摘的相关文章

【书摘】《Node.js从入门到精通》

1. npm 安装其他包 npm install  [module_name]     全局安装 npm install  -g  [module_name] 查看包文档   npm doc  [module_name] 查看bug      npm bug  [module_name] 查看源码      npm edit  [module_name] 2. 用package.json 来保存管理项目引用的包的依赖关系.避免一个一个的安装. 3. Npm : http://npmjs.org/

Node.js开发入门—语音合成示例

出于项目需要,搞了一个语音合成(TTS)的小示例,使用的是OKVoice. 我想在PC上测试,OKVoice的快速接入API可以实现我的目的,文档在这里:http://dev.okvoice.com/file.php. 直接上代码吧,okVoiceTts.js,内容如下: var http = require('http'); var fs =require('fs'); var crypto = require('crypto'); var util = require('util'); va

Node.js开发入门—使用对话框ngDialog

做网站经常会遇到弹出对话框获取用户输入或弹出对话框让用户确认某个操作之类的情景,有一个基于AngularJS的扩展模块可以帮我们优雅地完成这类事情:ngDialog. ngDialog在github上提供了一个示例网页,演示了它的各种用法,在这里:https://github.com/likeastore/ngDialog/blob/master/example/index.html.ngDialog的github主页的readme也对常用的指令和服务做了较为详细的介绍,可以参考.我这篇就纯粹是

Node.js开发入门—Stream用法详解

Stream是Node.js中非常重要的一个模块,应用广泛.一个流是一个具备了可读.可写或既可读又可写能力的接口,通过这些接口,我们可以和磁盘文件.套接字.HTTP请求来交互,实现数据从一个地方流动到另一个地方的功能. 所有的流都实现了EventEmitter的接口,具备事件能力,通过发射事件来反馈流的状态.比如有错误发生时会发射"error"事件,有数据可被读取时发射"data"事件.这样我们就可以注册监听器来处理某个事件,达到我们的目的. Node.js定义了R

Node.js开发入门—Angular简单示例

在"使用AngularJS"中,我们提到了如何在Node.js项目中引入AngularJS,这次提供一个非常简单的示例,演示AngularJS里的指令.数据绑定.服务等内容. 我准备做Web后台管理系统,不同的管理员会有不同的权限,管理员登录后看到的菜单和他的权限有关,能看到什么,是动态生成的(类似RBAC).本文的示例从这个项目而来,当然,现在还是最简单的. 如果没有特别说明,后面我们用到的示例都使用express generator生成. Angular小demo 先搞起来吧. 第

Node.js开发入门—UDP编程

Node.js也提供了UDP编程的能力,相关类库在"dgram"模块里. 与TCP不同,UDP是无连接的,不保障数据的可靠性,不过它的编程更为简单,有时候我们也需要它.比如做APP的统计或者日志或者流媒体,很多流媒体协议都会用到UDP,网上一搜一大堆. 使用UDP,如果你要发送数据,只需要知道对方的主机名(地址)和端口号,扔一消息过去即可.至于对方收不收得到,听天由命了.这就是数据报服务,类似快递或邮件. 我们这次来介绍一下Node.js里的UDP编程,我会提供一个UDP版本的echo

Node.js开发入门—使用http访问外部世界

Node.js的http模块,不但可以构建服务器,也可以作为客户端类库来访问别的服务器.关键就在两个方法: http.request(options[,callback]) http.get(path[,callback]) 除了http,还会用到FileSystem模块和Stream中的stream.Readable和stream.Writable. 先来大概介绍一下相关API吧. API解释 http.request()方法接受一个options参数,这个参数可以是对象,用来指明你要访问的网

Node.js开发入门—套接字(socket)编程

Node.js的net模块提供了socket编程接口,方便我们利用较为底层的套接字接口来实现应用协议.这次我们看一个简单的回显服务器示例,包括服务端和客户端的代码. 使用JavaScript也可以进行套接字编程,哈哈,这酸爽! 代码 分服务器和客户端两部分来说吧. echoServer代码分析 echoServer.js: var net = require("net"); // server is an instance of net.Server // sock is an ins

Node.js开发入门—notepad++ for Node.js

对于Node.js开发,论IDE的话,Webstorm是不二的选择,但它是收费的(可免费使用30天).一开始,我们先将就一下,使用notepad++来编写Node.js应用.这样做还有一大好处:没有关于Node.js的代码高亮和自动补全,可以更好地敦促我们使用在线API文档记忆各种类库API.死磕自己吧,enjoy it. notepad++的安装与配置 到"https://notepad-plus-plus.org/download/v6.8.2.html"这里下载吧,6.8.2版本

Node.js开发入门—使用AngularJS内置服务

在上一篇,"AngularJS简单示例"中演示了一个非常简单的使用Angular的小demo,那篇已经太长,原本要介绍的一些内容只好单另开篇了.这些内容,就是如何使用Angular服务. 我们还是基于"AngularJS简单示例"中的示例来改造一下.新的示例,能从Node.js+Express构造的服务器上获取管理菜单.为了实现这个,需要做几部分改造: 服务器提供adminMenu的下载功能,需要修改app.js,处理路由 修改Angular实现的控制器x-cont