【发布时间】:2010-11-27 13:01:09
【问题描述】:
我正在为那些通过在顶部声明所有变量并将它们初始化为 null/0/whatever 的人清理 Java 代码,而不是在以后需要它们时声明它们。
对此有哪些具体指导方针?一种或另一种方式是否有优化原因,或者一种方式只是好的做法?是否有任何情况下可以接受偏离正确的做事方式?
【问题讨论】:
标签: java syntax variables coding-style
我正在为那些通过在顶部声明所有变量并将它们初始化为 null/0/whatever 的人清理 Java 代码,而不是在以后需要它们时声明它们。
对此有哪些具体指导方针?一种或另一种方式是否有优化原因,或者一种方式只是好的做法?是否有任何情况下可以接受偏离正确的做事方式?
【问题讨论】:
标签: java syntax variables coding-style
在尽可能靠近您使用它们的第一个位置声明变量。这实际上与效率无关,但会使您的代码更具可读性。声明的变量越接近使用它的位置,以后阅读代码时必须做的滚动/搜索就越少。将变量声明为更接近它们使用的第一个位置也会自然地缩小它们的scope。
【讨论】:
正确的方法是在第一次使用变量时准确地声明它们,并最小化它们的范围,以使代码更容易理解。
在函数顶部声明变量是 C 的保留(在需要的地方),并且绝对没有优势(变量范围仅存在于源代码中,在字节码中,所有局部变量都按顺序存在于堆栈中反正)。永远不要这样做。
有些人可能试图通过声称它“更简洁”来为这种做法辩护,但任何需要在方法中“组织”代码通常都强烈表明该方法太长了。
【讨论】:
来自Java Code Conventions、Chapter 6 on Declarations:
6.3 放置
仅将声明放在开头 块。 (块是任何代码 用大括号“{”和 "}".) 不要等待声明变量 直到他们第一次使用;它可能会混淆 粗心的程序员和妨碍代码 范围内的可移植性。
void myMethod() { int int1 = 0; // beginning of method block if (condition) { int int2 = 0; // beginning of "if" block ... } }该规则的一个例外是 for 循环的索引,在 Java 中 可以在for语句中声明:
for (int i = 0; i < maxLoops; i++) { ... }避免隐藏的本地声明 更高级别的声明。为了 例如,不要声明相同的 内部块中的变量名:
int count; ... myMethod() { if (condition) { int count = 0; // AVOID! ... } ... }
【讨论】:
如果您在函数体内的各个孤立位置使用了千亿个变量,那么您的函数太大了。
如果您的函数大小易于理解,则“全部预先”和“按需”没有区别。
唯一的非预先变量将在 for 语句的主体中。
for( Iterator i= someObject.iterator(); i.hasNext(); )
【讨论】:
if 和 else 结构必须具有并行的副作用,并且只有一侧的局部变量非常罕见。
4.8.2.2 需要时声明
局部变量不习惯在它们的开头声明 包含块或类似块的构造。相反,局部变量是 声明接近它们首次使用的点(在合理范围内),以 最小化他们的范围。局部变量声明通常有 初始化器,或在声明后立即初始化。
好吧,我会按照谷歌的做法,从表面上看,在方法/函数的顶部声明所有变量似乎会“更整洁”,很明显声明变量是有益的有必要的。但这是主观的,无论您感觉如何直观。
【讨论】:
我发现根据需要声明它们比在开始时声明它们会产生更少的错误。我还发现,在尽可能小的范围内声明它们也可以防止错误。
几年前,当我查看由声明位置生成的字节码时,我发现它们或多或少是相同的。偶尔会有差异,具体取决于分配的时间。甚至是这样的:
for(Object o : list) {
Object temp = ...; //was not "redeclared" every loop iteration
}
对
Object temp;
for(Object o : list) {
temp = ...; //nearly identical bytecoode, if not exactly identical.
}
大致相同
【讨论】:
我现在正在做同样的事情。我正在修改的代码中的所有变量都声明在函数的顶部。我已经看到,我一直在查看这个声明了几个变量但从未使用过或声明了它们并且正在使用它们完成操作(即解析String,然后使用日期/设置Calendar对象)字符串中的时间值),但从不使用生成的 Calendar 对象。
我正在通过从顶部获取声明并将它们在函数中向下移动到更接近使用它的位置的方式来清理并清理它们。
【讨论】:
在比所需范围更广的范围内定义变量会严重影响可理解性。有限的范围表明这个变量只对这个小代码块有意义,你在进一步阅读时不能考虑。这是一个非常重要的问题,因为大脑的短期工作记忆很小(它说平均而言你只能跟踪 7 件事)。少一件需要跟踪的事情很重要。
同样,您确实应该尽量避免字面意义上的变量。尝试一次分配所有事物,并将它们声明为最终的,以便读者知道这一点。不必跟踪某件事是否发生了变化,从而真正减轻了认知负担。
【讨论】:
原则:将局部变量声明放置在尽可能靠近它们第一次使用的位置,而不是简单地放在方法的顶部。考虑这个例子:
/** Return true iff s is a blah or a blub. */
public boolean checkB(String s) {
// Return true if s is a blah
... code to return true if s is a blah ...
// Return true if s is a blub. */
int helpblub= s.length() + 1;
... rest of code to return true is s is a blah.
return false;
}
这里将局部变量helpblub放在需要的地方,在代码中测试s是否为blub。它是实现“Return true is s is a blub”的代码的一部分。 将 helpblub 的声明作为方法的第一个语句绝对没有逻辑意义。可怜的读者会想,为什么会有那个变量?有什么用?
【讨论】:
我认为实际上可以客观地证明,declare-at-the-top 样式更容易出错。
如果您通过随机移动行来更改任一样式的代码(以模拟合并失败或有人不假思索地剪切+粘贴),那么在顶部声明样式有更大的编译机会,而功能错误。
我不认为 declare-at-the-top 有任何不归结为个人喜好的相应优势。
所以假设你想编写可靠的代码,学习更喜欢做即时声明。
【讨论】:
这是一个可读性和个人喜好的问题,而不是性能问题。编译器不在乎,无论如何都会生成相同的代码。
【讨论】:
我见过人们在函数的顶部和底部声明。我更喜欢顶部,在那里我可以快速看到它们。这是一个选择和偏好的问题。
【讨论】: