-1是一个神奇的数字?反模式?代码味道?当局的报价和指南 [英] Is -1 a magic number? An anti-pattern? A code smell? Quotes and guidelines from authorities

查看:130
本文介绍了-1是一个神奇的数字?反模式?代码味道?当局的报价和指南的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

常数滥用?

我见过 -1 在各种API中使用,最常用于搜索具有从零开始的索引的集合时,通常用于指示未找到索引。这有效,因为 -1 从来都不是合法的索引。似乎任何负数都应该有效,但我认为 -1 几乎总是被用作某种(不成文的?)约定。

I've seen -1 used in various APIs, most commonly when searching into a "collection" with zero-based indices, usually to indicate the "not found" index. This "works" because -1 is never a legal index to begin with. It seems that any negative number should work, but I think -1 is almost always used, as some sort of (unwritten?) convention.

我想至少暂时将范围限制为Java。我的问题是:

I would like to limit the scope to Java at least for now. My questions are:


  • Sun使用 -1 的官方消息是什么?作为这样的特殊返回值?

  • 关于这个问题有哪些引用,例如James Gosling,Josh Bloch,甚至是Java之外的其他权威人士?

  • 过去关于这个问题的一些值得讨论的讨论是什么?

  • What are the official words from Sun regarding using -1 as a "special" return value like this?
  • What quotes are there regarding this issue, from e.g. James Gosling, Josh Bloch, or even other authoritative figures outside of Java?
  • What were some of the notable discussions regarding this issue in the past?

推荐答案

这是一种常见的习语,其中的类型不包括范围检查。 越界值用于表示几种条件之一。这里,返回值表示两件事:1)是找到的字符,2)它在哪里找到。
使用-1表示未找到的非负索引简洁地编码两者将这些值转换为一个值,并且 not-found 这一事实不需要返回索引。

This is a common idiom in languages where the types do not include range checks. An "out of bounds" value is used to indicate one of several conditions. Here, the return value indicates two things: 1) was the character found, and 2) where was it found. The use of -1 for not found and a non-negative index for found succinctly encodes both of these into one value, and the fact that not-found does not need to return an index.

具有严格范围检查的语言,例如Ada或Pascal,该方法可以实现为(伪代码)

In a language with strict range checking, such as Ada or Pascal, the method might be implemented as (pseudo code)

   bool indexOf(c:char, position:out Positive);

正面是int的子类型,但是限制为非负值。

Positive is a subtype of int, but restricted to non-negative values.

这将找到/未找到的标志与该位置分开。该位置作为输出参数提供 - 基本上是另一个返回值。它也可以是一个输入输出参数,从给定位置开始搜索。这里不允许使用-1来表示not-found,因为它违反了Positive类型的范围检查。

This separates the found/not-found flag from the position. The position is provided as an out parameter - essentialy another return value. It could also be an in-out parameter, to start the search from a given position. Use of -1 to indicate not-found would not be allowed here since it violates range checks on the Positive type.

java中的替代方案是:

The alternatives in java are:


  • 抛出一个例外:这不是一个好的选择,因为没有找到一个字符并不是特例。

  • 将结果分成几种方法,例如 boolean indexOf(char c); int lastFoundIndex(); 。这意味着对象必须保持状态,这在并发程序中不起作用,除非状态存储在线程本地存储中,或者使用同步 - 所有可观的开销。

  • 返回位置并分别找到标志:例如 boolean indexOf(char c,Position pos)。这里,创建位置对象可能被视为不必要的开销。

  • 创建多值返回类型

  • throw an exception: this is not a good choice here, since not finding a character is not an exceptional condition.
  • split the result into several methods, e.g. boolean indexOf(char c); int lastFoundIndex();. This implies the object must hold on to state, which will not work in a concurrent program, unless the state is stored in thread-local storage, or synchronization is used - all considerable overheads.
  • return the position and found flag separately: such as boolean indexOf(char c, Position pos). Here, creating the position object may be seen as unnecessary overhead.
  • create a multi-value return type

,例如

class FindIndex {
   boolean found;
   int position;
}

FindIndex indexOf(char c);

虽然它明确区分了返回值,但它会受到对象创建开销的影响。其中一些可以通过将 FindIndex 作为参数传递来减轻,例如:

although it clearly separates the return values, it suffers object creation overhead. Some of that could be mitigated by passing the FindIndex as a parameter, e.g.

FindIndex indexOf(char c, FindIndex start);

顺便提一下,多个返回值将成为java(oak)的一部分,但是在之前被砍掉了1.0减少发布时间。 James Gosling 他希望他们被包括在内。它仍然是希望的功能

Incidentally, multiple return values were going to be part of java (oak), but were axed prior to 1.0 to cut time to release. James Gosling says he wishes they had been included. It's still a wished-for feature.

我的看法是使用魔术值是在单个返回值中编码多值结果(标志和值)的实用方法,而不需要过多的对象创建开销。

My take is that use of magic values are a practical way of encoding a multi-valued results (a flag and a value) in a single return value, without requiring excessive object creation overhead.

但是,如果使用魔术值,如果它们在相关的api调用中保持一致,则使用它会更好。例如,

However, if using magic values, it's much nicer to work with if they are consistent across related api calls. For example,

   // get everything after the first c
   int index = str.indexOf('c');
   String afterC = str.substring(index);

Java在此处不足,因为在的调用中使用-1 substring 将导致 IndeOutOfBoundsException 。相反,如果将负值视为从字符串末尾开始,则在使用-1调用时,子字符串返回可能更加一致。对错误条件的魔术值的批评者说,可以忽略返回值(或假设为正数)。以有用的方式处理这些魔术值的一致api将减少检查-1并允许更清晰的代码的需要。

Java falls short here, since the use of -1 in the call to substring will cause an IndeOutOfBoundsException. Instead, it might have been more consistent for substring to return "" when invoked with -1, if negative values are considered to start at the end of the string. Critics of magic values for error conditions say that the return value can be ignored (or assumed to be positive). A consistent api that handles these magic values in a useful way would reduce the need to check for -1 and allow for cleaner code.

这篇关于-1是一个神奇的数字?反模式?代码味道?当局的报价和指南的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆