java - 循环增量 : Which is "better"?

标签 java coding-style

当您有一个表示为数组的循环缓冲区,并且您需要环绕索引(即,当您达到可能的最高索引并递增它时),是否“更好”:

return (++i == buffer.length) ? 0: i;

或者

return ++i % buffer.length;

使用模运算符有什么缺点吗?它比第一个解决方案的可读性差吗?

编辑:

当然应该是++i而不是i++,改了。

编辑 2:

一个有趣的注意事项:我在 Doug Lea 的 ArrayBlockingQueue 实现中找到了第一行代码。

最佳答案

Update: OP has admitted in a comment that it should have been pre-increment instead. Most of the other answers missed this. There lies proof that the increment in this scenario leads to horrible readability: there's a bug, and most people couldn't see it.

最易读的版本如下:

return (i == buffer.length-1) ? 0 : i+1;

使用 ++ 会给检查增加不必要的副作用(更不用说我强烈认为你应该改用预增量)

原代码有什么问题?让我们看看,好吗?

return (i++ == N) ? 0 : i; // OP's original, slightly rewritten

所以我们知道:

  • ipost 递增的,所以当 i == N-1return 语句之前时,这将返回 N 而不是立即返回 0
    • 这是故意的吗?大多数时候,目的是使用 N 作为唯一上限
  • 变量名 i 按照命名约定暗示了一个局部变量,但真的是这样吗?
    • 由于副作用,需要仔细检查它是否是一个字段

相比之下:

return (i == N-1) ? 0 : i+1; // proposed alternative

这里我们知道:

  • i 不被修改,不管是局部变量还是字段
  • i == N-1时,返回值为0,比较典型的场景

% 方法

或者,您也可以使用 % 版本,如下所示:

return (i+1) % N;

% 有什么问题?好吧,问题是即使大多数人认为它是 modulo 运算符,但它不是!它是余数 运算符 ( JLS 15.17.3 )。很多人经常把这个弄糊涂。这是一个经典的例子:

boolean isOdd(int n) {
   return (n % 2) == 1; // does this work???
}

那个密码坏了!!!它为所有负值返回 false!问题是 -1 % 2 == -1,尽管在​​数学上 -1 = 1 (mod 2)

% 可能很棘手,这就是为什么我推荐使用三元运算符版本。不过,最重要的部分是消除增量的副作用。

另见

关于java - 循环增量 : Which is "better"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2801581/

相关文章:

c# - MSBuild - 将来自 editorconfig 的警告视为错误(在构建期间强制执行)

java - 尝试从 Firebase 数据库中的子值获取 key

java - 来自 .NET Webservice 的压缩数组字节 Java

java - 运行批处理脚本时自动关闭对话框

Python:Pep8 E128 缩进错误......这怎么能被样式化?

php - isset() vs strlen() - 快速/清晰的字符串长度计算

html - CSS 元素规则

c++ - 使用数据库模型(键)来引用运行时对象,好主意还是坏主意?

java - 如何删除字符串中特定位置的数值

java - Java中字节流转字符流