为什么要将局部变量的作用域最小化?

嗨,本篇文章来说说 Java 的一个小细节:为什么要将局部变量的作用域最小化?

明人不说暗话啊。这篇文章的灵感来源于《Effective Java》,这本书我买了有好长好长一段时间了,书页都已经泛黄,烙下了时间的痕迹,但我仍然还没有把这本书读完。说来惭愧啊。

为什么呢?总感觉这本书的中文翻译有点拙劣,读起来烦闷枯燥。明明感觉作者说得非常有道理,但就是提不起半点兴致。

(说完这句话,总觉得有点对不住这本书的译者,毕竟吐槽容易,分享难啊。)

为什么要说这些废话呢,因为怕大家觉得这是不值一提的细节,但往往细节决定成败啊。大家不妨换一种比较轻松的心态来读一读。反正我是不怎么喜欢高谈阔论的文章,读完后往往只能感慨一句:“说得不错啊”,但也仅此而已。

好了,来步入正题。

String [] strs = {"洛阳","牡丹","甲天下"};List<String> list = Arrays.asList(strs);

Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {    String s = (String) iterator.next();    System.out.println(s);}

list.add("沉默王二");Iterator<String> iterator1 = list.iterator();while (iterator.hasNext()) {    String s = (String) iterator1.next();    System.out.println(s);}

大家用“肉眼”看完上面这段代码后,会觉得有问题吗?

如果不细心的话,好像真的很难发现“复制-粘贴”引发的这个问题:第二个 while 循环的条件中使用了之前的变量 iterator,而不是它应该使用的 iterator1(粘贴后遗漏了变量的修改)。这个问题将会导致代码在运行的时候抛出 java.lang.UnsupportedOperationException 的错误。

说句实在话,在敲代码的这十年来,没少复制粘贴,没少因为粘贴后变量没有修改彻底,而导致出现了各种意料之外的 bug。

假如把变量的作用域最小化的话,还真的能够减少这种因为“复制-粘贴”而导致出现的错误。比如说把 while 循环改造成 for 循环。

for (Iterator<String> iterator = list.iterator();iterator.hasNext();) {    String s = (String) iterator.next();    System.out.println(s);}

list.add("沉默王二");for (Iterator<String> iterator = list.iterator();iterator.hasNext();) {    String s = (String) iterator.next();    System.out.println(s);}

第二个 for 循环使用了和第一个 for 循环一模一样的代码,连 iterator 这个变量也不需要修改了。

从另一方面来看的话,for 循环比 while 循环更简短,可读性更好。for 循环还有另外一种最常用的写法,示例如下。

for (int i = 0; i < list.size(); i++) {    System.out.println(list.get(i));}

但这种写法仍有改进的地方,因为从字节码的角度来看,每次循环都要调用一次 size() 方法。

2: iload_13: aload_04: getfield      #4                  // Field list:Ljava/util/List;7: invokeinterface #5,  1            // InterfaceMethod java/util/List.size:()I12: if_icmpge     4015: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;18: aload_019: getfield      #4                  // Field list:Ljava/util/List;22: iload_123: invokeinterface #7,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;28: checkcast     #8                  // class java/lang/String31: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V34: iinc          1, 137: goto          240: return

size() 方法虽然简短,但也有消耗啊。都有什么消耗呢?说几个专业名词大家感受一下,比如说:创建栈帧、调用方法时保护现场、调用方法完毕后恢复现场。

(容许我尴尬一下,在写这篇文章之前,我一直用的上面这种 for 循环格式。看来写文章还是能够督促自己进步啊。)

怎么改进呢,看下面这种写法(强烈推荐啊)。

for (int i = 0, n = list.size(); i < n; i++) {    System.out.println(list.get(i));}

在 for 循环内部声明两个变量:i 和 n,n 用来保存 i 的极限值,这样就减少了 size() 方法的调用次数(仅有一次了)。

再来看一段代码。

String pre_name = "沉默";String last_name = "王二";

System.out.println(pre_name);System.out.println(last_name);

上面这段代码看起来挺规整的,没什么问题,对吧?它没有遵守约定——将局部变量的作用域最小化。

pre_name 变量的作用域结束的有点晚;last_name 变量的作用域开始的有点早。假如第一个 System.out.println() 出错的话,last_name 的声明就变得毫无意义了。

(这只是一个例子,变量的处理方法可能比 System.out.println() 复杂得多。)

好的写法应该是下面这样子。

String pre_name = "沉默";System.out.println(pre_name);

String last_name = "王二";System.out.println(last_name);

有人可能觉得这不是在吹毛求疵吗?真不是的,变量就应该是在第一次使用它的时候声明。否则的话,变量的作用域要么开始的太早,要么结束的太晚。

好了,这篇文章到此就结束了,非常的简短,但讲清楚了“为什么要将局部变量的作用域最小化”。

原文地址:https://www.cnblogs.com/qing-gee/p/11616726.html

时间: 2024-11-05 16:02:25

为什么要将局部变量的作用域最小化?的相关文章

第45条:将局部变量的作用域最小化

将局部变量的作用域最小化,可以增强个代码的可读性和可维护性,并降低出错的可能性. 方法: 1.在第一次使用它的地方声明.如果变量在使用之前声明,对于试图理解程序功能的读者来说,多了一个分散注意力的因素,等到用到该变量的时候,可能已经记不起变量的类型或者初始值了. 2.几乎每个局部变量的声明都应该包含一个初始化表达式.如果还没有足够的信息对一个变量进行有意义的初始化,就应该推迟这个声明,直到可以初始化为止.例外,try-catch语句,如果一个变量被一个方法初始化,而这个方法有可能抛出一个受检异常

11、将局部变量的作用域最小化

将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性. 早期的程序设计语言要求局部变量必须在代码块的开头处声明,很多程序员保持这种习惯,但这是不好的.最好的方式就是在初次使用它的地方进行声明,否则等到运用的时候可能已经记不起这个变量名称,或者类型,这对于开发来说,或者阅读代码的人来说都是一件分散注意力的因素. 而如果在开头处声明,通常意味着它可以被应用到多个域当中,那你就可能在别的域中误用这个变量,尤其是在现今代码拷贝成习惯的开发日常,而从编译角度讲,代码是没有错误的,所

第四十五条:将局部变量的作用域最小化

将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性. 要使局部变量的作用域最小化,最有力的方法就是在第一次使用它的地方声明. 如果过早的对变量进行声明,首先会造成混乱,对于试图理解程序功能的读者来说,这又多了一种只会分散他们注意力的因素.等到 用该变量的时候,读者可能已经记不起该变量的类型或者初始值了.其次,过早的声明局部变量不仅会使它的作用域过早的扩展,而且 结束得也过于晚了.局部变量的作用域从它被声明的点开始扩展,一直到外围块的结束处.如果变量是在"使用它的块&qu

第八章:通用程序设计。ITEM45:将局部变量的作用域最小化。

1.将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性.在 C 语言中要求局部变量必须在一个代码块的开头处进行声明,出于习惯,有些开发者延续了这样的做法. 这个习惯需要改正,Java 提供了你在代码块的任何地方声明变量的语法支持. 2."要使局部变量的作用域最小化,最有力的实践就是在第一次使用它的地方声明".如果过早的声明,开发者就有可能在真正使用该变量的时候忘记了它的类型或者初始值了,而且也会带来代码块内变量名的名字污染问题,由此引发的 Bug,往往是令人极

Java之路(六) 局部变量作用域最小化

将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性. 将局部变量的作用域最小化的方法有: 方法1:在第一次使用某个局部变量的地方进行声明. a.Java可以在任何可以出现语句的地方声明变量. 这条规则可以让我们在需要的地方声明变量,从而缩小作用域,如果没有这个前提,后面的一切都不成立了. b.过早的声明局部变量不仅会是它的作用域过早的扩展,而且结束的过于晚了. 要正确理解这句话.局部变量的作用域从它被声明的点开始扩展,一直到外围块的结束处.见下图: 如果变量是在“使用它

第13条:使类和成员的可访问性最小化

区别设计良好的模块和设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节.设计良好的模块会隐藏所有的实现细节,把它的API于它的实现清晰地隔离开来.然后,模块之间通过它们的API进行通信,一个模块不需要知道其他模块的内部工作情况,这个概念称为信息隐藏或封装.使类和成员的可访问性最小化可以有效的解除系统中各个模块的耦合度.实现每个模块的独立开发.使得系统更加的可维护,更加的健壮.对于顶层的(非嵌套的)类和接口,只有两种可能的访问级别,包级私有的和公有的

Centos7最小化系统安装_配置

本文总结了作者使用centos最小化安装时,碰到的问题和解决方案. 网络问题.作者使用虚拟机安装时,网卡并没有激活.操作: 1 cd /etc/sysconfig/network-script 2 vi 要编辑的网卡 3 更改 onboot = yes 4 # 重启network 5 systemctl restart network 使用ip address命令查看IP地址 使用XSHELL远程连接虚拟机 1 #检测SSHD服务是否开启 2 systemctl status sshd 3 #如

How Javascript works (Javascript工作原理) (十四) 解析,语法抽象树及最小化解析时间的 5 条小技巧

个人总结:读完这篇文章需要15分钟,文章介绍了抽象语法树与js引擎解析这些语法树的过程,提到了懒解析--即转换为AST的过程中不直接进入函数体解析,当这个函数体需要执行的时候才进行相应转换.(因为有的函数体只是声明了,并没有实际被调用) 解析,语法抽象树及最小化解析时间的 5 条小技巧 这是 JavaScript 工作原理的第十四章. 概述 我们都知道运行一大段 JavaScript 代码性能会变得很糟糕.代码不仅仅需要在网络中传输而且还需要解析,编译为字节码,最后运行.之前的文章讨论了诸如 J

Linux的最小化安装

在安装Linux操作系统时,应遵循最小化安装的原则,即不需要或不确定是否需要的包就不安装,这是一个良好的习惯.最小化安装可以在一定程度上为系统瘦身,但更为重要的一点就是它可以提高系统安全性.本文以CentOS6.6为例,来说明最小化安装Linux操作系统的步骤.在CentOS6.6包选择界面之前的安装过程就不再赘述了,直接进入包选择界面,见以下截图: 在安装完成后,如果发现部分包组没有被选择(当然也可能系统并不是你安装的),可以使用yum groupinstall “Desktop” “X wi