2010-07-16 2 views
6

Вы бы бросаться IllegalStateException если:Является ли IllegalStateException подходящим для неизменяемого объекта?

  1. метод не в состоянии выполнять свою работу из-за ценности (ы) одного или нескольких полей
  2. Эти поля final и назначается только в конструкторе?

Пример учебника: ваш класс является неизменным Collection<BigInteger>, и ваш метод должен возвращать максимальный элемент, но этот экземпляр пуст.

Я прочитал Kevin Bourillon`s blog post по этому вопросу, и я не уверен, какое правило применяется.

UnsupportedOperationException - это означает, что вызванный метод всегда будет терпеть неудачу для экземпляра этого класса (конкретного типа), независимо от того, как был создан экземпляр.

Определенно нет. Многие экземпляры этого класса не пусты, и операция была бы успешной.

IllegalStateException - ... там существует по крайней мере одно альтернативное состояние, что экземпляр в вопросе мог бы быть в, который бы прошел проверку ... < надрез > ... Отметим также, что это исключение целесообразно, действительно ли можно реально мутировать этот аспект состояния экземпляра, или уже слишком поздно.

Не совсем. Этот экземпляр был сконструирован с нулевой длиной, поэтому этот экземпляр не является и никогда не мог быть непустым.

IllegalArgumentException - исключение этого исключения означает, что для этого параметра существует хотя бы одно другое значение, которое могло бы привести к передаче вопроса.

Может применяться, если рассматриваемый параметр является неявным параметром this. Это исключение, которое я соблазн бросить, но я обеспокоен тем, что это может сбить с толку.


Обновление: изменен пример из Collection<Integer> к Collection<BigInteger> потому тот факт, что существует единичный элемент (Integer.MIN_VALUE) отвлекает от вопроса.

+0

В этом вопросе есть две разные вещи. ** Один ** должен иметь метод утилиты, который возвращает максимум данной коллекции (что, как указывает Джон, подобно методу Collections.max) ** other ** находится в заголовке вопроса, * неизменяемом объекте * с максимальным методом, возвращающим либо максимальное значение делегированного объекта, либо его самого.Этот второй сценарий - тот, на который я отвечаю http://stackoverflow.com/questions/3267958/is-illegalstateexception-appro-for-an-immutable-object/3268353#3268353 – OscarRyz

ответ

4

Думаю, IllegalStateException подходит. Экземпляр мог быть в правильном состоянии, если он был построен правильно (т. Е. Часть «уже слишком поздно»).

+2

В этом случае это должно быть незаконное исключение аргумента, но ** когда ** вы понимаете, что объект создается неправильно. – OscarRyz

+1

@OscarRyz Это справедливо только в том случае, если ни один из его методов не может обрабатывать заданное состояние. Если getMax() является единственной функцией, для которой состояние является незаконным, я бы сказал, что IllegalStateException является подходящим. – ILMTitan

+2

ILM Mhh yeap, вы правы в этом, но я в этом случае предпочитаю использовать UnsupportedOperationException, но это сложно ..mmmhh как насчет .. 'UnsopporteOperationCausedByIllegalStateOriginatedByIllegalArgumentException' :) – OscarRyz

11

Это не похоже ни на один из обычных классов исключений, о которых вы упомянули выше, вписывается в пример учебника.

Вы должны бросить NoSuchElementException, так как это именно то, что делает метод Collections.max().

+3

+1 для поиска некоторого «уровня техники». –

+0

Мне обычно не нравятся значения исключений, такие как '-1', но в этом случае * есть * элемент идентификации:' Integer.MIN_VALUE'. Это просто показывает, что я выбрал плохой пример, поэтому я собираюсь отредактировать вопрос, чтобы ссылаться на 'BigInteger' вместо' Integer' :-) – finnw

+5

+1 на NoSuchElementException, но 'return -1' - плохая идея. Поэтому возвращается 'Integer.MIN_VALUE', который, если возвращаемый, все равно не скажет вам, действительно ли оно имеет максимальное значение или нет (что относительно коллекции, содержащей только Integer.MIN_VALUE? Null - лучший выбор, чем тот, но не такой хороший, как Исключение IMO. –

3

Если состояние класса действительно (пустая коллекция), максимальный элемент равен нулю.Если состояние недействительно, исключение IllegalArgumentException должно было быть выброшено во время строительства.

+0

+1 точно. .. – OscarRyz

3

IllegalStateException подходит ближе всего к тому, что вы хотите: «это исключение подходит независимо от того, действительно ли можно мутировать этот аспект состояния экземпляра».

Not UnsupportedOperationException, так как это может преуспеть для некоторого экземпляра этого класса и бросание IllegalArgumentException для метода, который (предположительно) не принимает аргументов, безусловно, путает людей.

+0

Но неизменяемый объект имеет только одно состояние ...: -/ – OscarRyz

+0

Нет, у него есть только одно ДОСТУПНОЕ состояние. См. Вторую причину моего первого предложения. – DJClayworth

2

Is IllegalStateException подходит для неизменяемого объекта?

Нет, поскольку неизменяемые объекты имеют только одно состояние и не могут быть перенесены из одного правового государства в другое.

Итак, вы построение неизменяемого объекта, и ваш объект должен иметь максимальный метод

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

Я этот случай IllegalAgumentException должен быть правильным, но не до тех пор, метод выполняется, но когда объект создан!

Итак, в этом случае, если у вас есть неизменяемая коллекция больших объектов, и вы создаете ее с нулевыми элементами, вы получаете «недопустимый аргумент» при создании коллекции, то есть когда вам нужно выбросить исключение.

Я согласен с Джоном, если ваш случай использования или в вашем анализе, вы готовы поддержать остальные операции, вы можете выбросить 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, потому что программа потерпит неудачу в случае создание, которое, в свою очередь, будет фиксировано во время разработки.

NoSuchElementException бросание будет, как:

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 имеют другую цель, поскольку он является способом утилиты (не неизменным объектом), он не может нести ответственность за создание пустой коллекции (его не было, когда это произошло), единственное, что он может сделать, это скажем «В этой коллекции нет такой вещи, как max», следовательно, NoSuchElementException.

Одно последнее замечание, RuntimeExceptions, should be used for programming mistakes only (те, которые могут быть решены путем тестирования приложения перед выпуском)

2

Вы должны выброшено UnsupportedOpertationException, потому что это то, что делает стандартной библиотеки Java в тех же обстоятельствах. Ваш пример - это код объекта классификатора . Эта модель была определена в "An Empirical Study of Object Protocols in the Wild":

Некоторых типов отключить определенные методы для жизни объекта. В категории типа качества экземпляр объекта вводит абстрактное состояние S в момент построения, который он никогда не покинет. Вызовы к экземпляру Метод m, если он отключен в состоянии S, всегда будет терпеть неудачу.

В вашем примере, ваш объект входит абстрактное состояние, которое я буду называть EmptyCollection во время строительства, и это никогда не покидает это состояние, потому что поле коллекции final. В абстрактном состоянии EmptyCollection все вызовы метода экземпляра getMax() всегда будут терпеть неудачу.

Beckman изучил Java-программы с открытым кодом, которые искали объектные протоколы и классифицировали полученные классы. Третьей наиболее распространенной категорией протоколов, отображаемой в 16,4% от отобранных протоколов, был тип классификатора.

бумажных списки Бекмана много примеров типа классификатора и я выбрал три из них, и в каждом случае недоступен метод выдает UnsupportedOperationException:

  1. При создании неизменяемого списка вызвав Colections.unmodifiableList(...), а затем вызвать метод add на в результате список.
  2. При создании java.nio.ByteBuffer, который не поддерживается массивом, а затем вызывает метод array.
  3. При создании java.imageio.ImageWriteParam, который не поддерживает сжатие, а затем вызывает метод setCompressionMode.

Обратите внимание, что эти примеры не следовать совету Кевина Бурийон, что вы процитировать. Неисправность этих методов зависит от того, как были созданы экземпляры. В примерах 1 и 2 случаи, которые преуспевают и терпят неудачу, могут иметь разные конкретные классы, поскольку List и ByteBuffer являются абстрактными. Однако ImageWriteParam является конкретным классом, поэтому один экземпляр ImageWriteParam может выдать UnsupportedOperationException, а другой - нет. Поскольку дизайнеры стандартной Java-библиотеки также определили типы исключений, я буду следовать их примеру вместо г-на Бурильона.

P.S. Вы должны использовать IllegalStateException, тогда как абстрактное состояние вашего объекта может измениться во время выполнения. Другие 83,6% примеров из бумаги Бекмана относятся к этому типу.

Смежные вопросы