在 Java 中,变量应该在函数的顶部声明,还是在需要时声明?
Posted
技术标签:
【中文标题】在 Java 中,变量应该在函数的顶部声明,还是在需要时声明?【英文标题】:In Java, should variables be declared at the top of a function, or as they're needed? 【发布时间】:2010-11-27 13:01:09 【问题描述】:我正在为那些通过在顶部声明所有变量并将它们初始化为 null/0/whatever 的人清理 Java 代码,而不是在以后需要它们时声明它们。
对此有哪些具体指导方针?一种或另一种方式是否有优化原因,或者一种方式只是好的做法?是否有任何情况下可以接受偏离正确的做事方式?
【问题讨论】:
【参考方案1】:在尽可能靠近您使用它们的第一个位置声明变量。这实际上与效率无关,但会使您的代码更具可读性。声明的变量越接近使用它的位置,以后阅读代码时必须做的滚动/搜索就越少。将变量声明为更接近它们使用的第一个位置也会自然地缩小它们的scope。
【讨论】:
提示:如果您使用 Visual Studio 高亮显示任意位置的变量并按 F12 将带您进入其定义(Shift + F12 将找到所有引用)。【参考方案2】:正确的方法是在第一次使用变量时准确地声明它们,并最小化它们的范围,以使代码更容易理解。
在函数顶部声明变量是 C 的保留(在需要的地方),并且绝对没有优势(变量范围仅存在于源代码中,在字节码中,所有局部变量都按顺序存在于堆栈中反正)。永远不要这样做。
有些人可能试图通过声称它“更简洁”来为这种做法辩护,但任何需要在方法中“组织”代码通常都强烈表明该方法太长了。
【讨论】:
【参考方案3】:来自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! ... ...
【讨论】:
你可耻,孙,你可耻! 以上内容仅供参考。你们都没有错/对,但我个人最喜欢 Bill & S.Lott 的答案 我怀疑这篇文章很老了,“迷惑粗心的程序员”指的是大量新接触 Java 的 C 程序员。现在这种情况已经很少见了,但文字从未修改过。 我完全同意这个答案。我既不是来自 java 世界也不是来自 C 世界,我只是更喜欢它。像往常一样,你们正在争论一些只是偏好问题......【参考方案4】:如果您在函数体内的各个孤立位置使用了千亿个变量,那么您的函数太大了。
如果您的函数大小易于理解,则“全部预先”和“按需”没有区别。
唯一的非预先变量将在 for
语句的主体中。
for( Iterator i= someObject.iterator(); i.hasNext(); )
【讨论】:
我正要写类似的东西。我唯一要补充的是,如果我声明的变量仅适用于方法中的特定块(例如,在 else 语句块中),我有时会偏离在方法的开头声明。 @Adamski:“在 else 块中”与“在 if 块中”变量非常非常罕见。if
和 else
结构必须具有并行的副作用,并且只有一侧的局部变量非常罕见。【参考方案5】:
来自Google Java Style Guide:
4.8.2.2 需要时声明
局部变量不习惯在它们的开头声明 包含块或类似块的构造。相反,局部变量是 声明接近它们首次使用的点(在合理范围内),以 最小化他们的范围。局部变量声明通常有 初始化器,或在声明后立即初始化。
好吧,我会按照谷歌的做法,从表面上看,在方法/函数的顶部声明所有变量似乎会“更整洁”,很明显声明变量是有益的有必要的。但这是主观的,无论您感觉如何直观。
【讨论】:
【参考方案6】:我发现根据需要声明它们比在开始时声明它们会产生更少的错误。我还发现,在尽可能小的范围内声明它们也可以防止错误。
几年前,当我查看由声明位置生成的字节码时,我发现它们或多或少是相同的。偶尔会有差异,具体取决于分配的时间。甚至是这样的:
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.
大致相同
【讨论】:
根据需要声明变量时,重构代码(将代码的sn-ps提取到方法中)也更容易。【参考方案7】:我现在正在做同样的事情。我正在修改的代码中的所有变量都声明在函数的顶部。我已经看到,我一直在查看这个声明了几个变量但从未使用过或声明了它们并且正在使用它们完成操作(即解析String
,然后使用日期/设置Calendar
对象)字符串中的时间值),但从不使用生成的 Calendar
对象。
我正在通过从顶部获取声明并将它们在函数中向下移动到更接近使用它的位置的方式来清理并清理它们。
【讨论】:
Jeremy - 我不知道您使用的是什么构建工具,但 Eclipse 有一个选项会在从未使用过局部变量时向您发出警告 - 只需单击两下即可删除那些:) 我见过的大多数 IDE 工具都不会捕获概念上未使用的,例如“MyObject o = new MyObject(); o.SetFlag(true);”然后再也没有使用过。当然,它在技术上被使用,但可能没有任何实际用途。 @MetroidFan2002 - 我没有使用构建工具。我在一个使用 jsp 页面的环境中,这些页面在执行时会生成 vxml 并将它们返回到 vxml 浏览器。此环境中的编辑器没有编译器,因此在我将其部署到测试服务器之前,即使是简单的语法错误也不会被捕获。我已经通过在 BlueJ 和 Notepad++ 中编写一些内容来解决这个问题,但我刚刚接受了这样一个事实,即这是一个糟糕的开发环境。幸运的是,该环境的下一个版本使用 Eclipse。 @James Schek,这只是一条更新评论。詹姆斯的评论至少不再适用于日食。【参考方案8】:在比所需范围更广的范围内定义变量会严重影响可理解性。有限的范围表明这个变量只对这个小代码块有意义,你在进一步阅读时不能考虑。这是一个非常重要的问题,因为大脑的短期工作记忆很小(它说平均而言你只能跟踪 7 件事)。少一件需要跟踪的事情很重要。
同样,您确实应该尽量避免字面意义上的变量。尝试一次分配所有事物,并将它们声明为最终的,以便读者知道这一点。不必跟踪某件事是否发生了变化,从而真正减轻了认知负担。
【讨论】:
【参考方案9】:原则:将局部变量声明放置在尽可能靠近它们第一次使用的位置,而不是简单地放在方法的顶部。考虑这个例子:
/** 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 的声明作为方法的第一个语句绝对没有逻辑意义。可怜的读者会想,为什么会有那个变量?有什么用?
【讨论】:
【参考方案10】:我认为实际上可以客观地证明,declare-at-the-top 样式更容易出错。
如果您通过随机移动行来更改任一样式的代码(以模拟合并失败或有人不假思索地剪切+粘贴),那么在顶部声明样式有更大的编译机会,而功能错误。
我不认为 declare-at-the-top 有任何不归结为个人喜好的相应优势。
所以假设你想编写可靠的代码,学习更喜欢做即时声明。
【讨论】:
【参考方案11】:这是一个可读性和个人喜好的问题,而不是性能问题。编译器不在乎,无论如何都会生成相同的代码。
【讨论】:
【参考方案12】:我见过人们在函数的顶部和底部声明。我更喜欢顶部,在那里我可以快速看到它们。这是一个选择和偏好的问题。
【讨论】:
你在想班级的顶层和底层吗?您不能真正在函数底部声明变量(在使用之后)。当我读到他的问题时,我想到的是成员变量而不是方法变量——所以也许这也是你在想的......以上是关于在 Java 中,变量应该在函数的顶部声明,还是在需要时声明?的主要内容,如果未能解决你的问题,请参考以下文章