代码之家  ›  专栏  ›  技术社区  ›  finnw

IllegalStateException是否适用于不可变对象?

  •  6
  • finnw  · 技术社区  · 14 年前

    你会扔一个 IllegalStateException

    1. 由于一个或多个字段的值,方法无法执行其任务
    2. final

    Collection<BigInteger> 方法应该返回最大元素,但是这个实例是空的。

    我读过 Kevin Bourillon`s blog post 我不知道哪条规则适用。

    绝对不是。这个类的许多实例都不是空的,操作应该已经成功了。

    IllegalStateException-。。。确实存在至少一个相关实例可能处于的备用状态,该状态将通过检查&书信电报;剪断>。。。另外请注意,无论是否可能实际改变实例状态的这一方面,或者已经太晚了,这个异常都是合适的。

    不完全是。这个实例是用零长度构造的,所以 不是也不可能是非空的。

    如果所讨论的参数是隐式 this 参数。这是一个例外,我很想抛出,但我担心它可能会令人困惑。


    :将示例从 Collection<Integer> 收藏<BigInteger> 因为事实上有一个身份元素( Integer.MIN_VALUE )分散注意力。

    6 回复  |  直到 14 年前
        1
  •  4
  •   Eric Petroelje    14 年前

    我想 IllegalStateException 在这里是合适的。如果实例构造正确(即“已经太晚了”部分),它可能处于正确的状态。

        2
  •  11
  •   Maarten Bodewes    9 年前

    你应该扔一个 NoSuchElementException 因为这正是 Collections.max() 方法确实如此。

        3
  •  3
  •   Dominik    14 年前

        4
  •  3
  •   DJClayworth    14 年前

    IllegalStateException最接近您想要的:“无论是否可能实际改变实例状态的这个方面,这个异常都是适当的”。

        5
  •  2
  •   Community c0D3l0g1c    7 年前

    不,因为不可变对象只有一个状态,不可能从一个合法状态转移到另一个合法状态。

    class YourObject {
        public BigInteger max(){ ... }
    }
    

    IllegalAgumentException 创建对象时!

    因此,在这个场景中,如果您有一个bigInteger的不可变集合,并且您使用零元素创建它,那么在创建集合时您将收到一个“无效参数”,这时您必须抛出异常。

    NoSuchElementException

    所以,抛出IllegalArgumentException就像:

      // this is my immutable object class
      final class YourObject {
          private final Collection<BigInteger> c;
          public YourObject( BigInteger ... values ) {
              if( values.length == 0 ) { 
                  throw new IllegalAgumentException("Must specify at least one value");
              }
              ... initialize the rest... 
          }
          public BigInteger max() {
              // find and return the max will always work 
          }
       } 
    

    客户:

       YourObject o  = new YourObject(); // throws IllegalArgumentException 
       // the rest is not executed....
       doSomething( o ) ; 
       ...
       doSomething( YourObject o ) {
            BigInteger maximum = o.max();
       }
    

    在这种情况下,你不需要检查任何东西 doSomething

    投掷 无接触异常

      final class YourObject {
          private final Collection<BigInteger> c;
          public YourObject( BigInteger ... values ) {
               // not validating the input  :-/ oh oh.. 
              ... initialize the rest... 
          }
          public BigInteger max() {
              if( c.isEmpty() ) { throw NoSuchElementException(); }
              // find and return the max will always work after this line
          }
       } 
    

    客户:

       YourObject o  = new YourObject(); // it says nothing
       doSomething( o ) ;
       ...
       doSomething( YourObject o ) {
            BigInteger maximum = o.max();// ooops!, why? what?...  
            // your object client will start questioning what did I do wrong
            // and chais of if( o != null && o.isEmpty() || moonPhaseIs... ) 
       }
    

    记住,如果一个程序失败了,你能做的最好的事情就是 to making it fail fast .

    Collections.max 有一个不同的目的,因为作为一个实用方法(不是一个不可变的对象),他不能为空集合的创建负责(发生这种情况时他不在场),他唯一能做的就是说 “这个收藏里没有马克斯” 因此没有任何例外。

    最后一句话,RuntimeExceptions, should be used for programming mistakes only (可以通过在发布应用程序之前测试它来修复的)

        6
  •  2
  •   Josh Sunshine    11 年前

    你应该扔一个 UnsupportedOpertationException 因为这就是Java标准库在相同情况下所做的。你的例子是 类型限定符对象协议 . 这种模式是在 "An Empirical Study of Object Protocols in the Wild" :

    某些类型在的生存期内禁用某些方法

    在您的示例中,您的对象进入一个抽象状态,我将调用它 空集合 final . 在 空集合 getMax() 实例方法总是会失败。

    Beckman研究了寻找对象协议的开源Java程序,并对产生的类进行了分类。第三个最常见的方案类别是 .

    Beckman的论文列出了许多类型限定符示例,我选择了其中的三个,在每种情况下,unavailable方法都会抛出一个 UnsupportedOperationException :

    1. 当您通过调用 Colections.unmodifiableList(...) 然后打电话给 add
    2. 当您创建 java.nio.ByteBuffer 然后调用 array 方法。
    3. java.imageio.ImageWriteParam 不支持压缩,然后调用 setCompressionMode 方法。

    听从凯文·布里隆的建议。这些方法的失败取决于实例的构造方式。在示例1和2中,成功和失败的实例可能属于不同的具体类,因为 List ByteBuffer ImageWriteParam 是一个具体的类,所以 图像写入RAM 我可以扔掉 而另一个可能不是。由于Java标准库的设计者也定义了异常类型,所以我将遵循他们的指导,而不是Bourillon先生的。

    另外,你应该使用 IllegalStateException 而不是对象的抽象状态 可以在运行时更改 . 贝克曼论文中其他83.6%的例子都属于这种类型。