Подтвердить что ты не робот

Сделать исключения более информативными

Есть ли способ сделать Java Exceptions более информативным?

Например, возьмите этот код из документов ClassCastException:

Object x = new Integer(0);
System.out.println((String)x);

Java предоставит мне ClassCastException с сообщением типа "Нельзя использовать что-то типа Integer to String". Как я могу заставить его сказать: "Невозможно использовать Integer 0 для строки"? И если я попытался передать String "foo" персонажу, чтобы заставить его сказать: "Невозможно передать String foo персонажу"? Итак, со значением объекта, который я пытался сделать.

Можно ли каким-то образом заменить стандартное ClassCastException более информативным, , поэтому мне не нужно вводить множество try/catch-блоков? Подкласс - это, конечно, вариант, но тогда мне придется вводить множество блоков try/catch.

Причина, по которой я спрашиваю, на самом деле связана с другим языком программирования, который компилируется в JVM, Clojure.

В Clojure новички часто совершают эту ошибку:

(def my-list ("foo" "bar"))

В результате появляется сообщение об ошибке:

java.lang.String cannot be cast to clojure.lang.IFn

Было бы очень полезно для новичков увидеть что-то вроде:

java.lang.String "foo" cannot be cast to clojure.lang.IFn

чтобы они поняли, что они пытаются использовать строку здесь как функцию.

Было бы неплохо иметь возможность вводить эти новые Исключения для учебной среды, не переписывая при этом Clojure компилятор. Он может быть решен на уровне REPL, но, тем не менее, поймать эти типы исключений. Тем не менее мне интересно, возможно ли это с помощью некоторых отличных приемов.

4b9b3361

Ответ 1

Эта проблема обсуждалась не последним Clojure Conj и обычно принимается как что-то для работы в компиляторе. После этого факта вы не можете много сделать, чтобы улучшить трассировку стека, но будьте уверены, что вы не единственный, кто хочет улучшить это.

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

Ответ 2

Ваш вопрос не имеет смысла. Возможно, дайте лучший пример. Единственное, что удаленно похоже на то, что вы пытаетесь сделать, это перехват исключений с помощью платформы с ориентированным на аспекты программирования (например, AspectJ). Вы можете заменить одно исключение на другое, но, вероятно, не даст вам возможности фактически получить доступ к объекту, который не удалось выполнить, как в вашем примере.

Ответ 3

Этот ответ был напечатан до того, как был изменен вопрос, и был указан Clojure.

Создайте собственный статический метод для литья в строку, например CastUtil.castString(). В этом методе вы можете проверить тип перед попыткой приведения и выбросить информативное исключение, включающее значение.

Чтобы упростить использование этого нового метода, вы также можете использовать import static следующим образом:

import static myutil.CastUtil.*;

Затем в вашем коде вы можете написать castString(someObject)

Ответ 4

Вы можете объединить свой блок кода с помощью try/catch:

Object x = new Integer(0);
try {
  System.out.println((String)x);
} catch (ClassCastException e) {
  throw new ClassCastException("Can't cast the Integer " + x + " to a String");
}

Ответ 5

В Clojure есть две структуры: clojure.stacktrace и

Усовершенствованная функция stacktrace:

user=> (use 'clojure.stacktrace)
nil
user=> (print-stack-trace *e 5)
clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException (NO_SOURCE_FILE:0)
 at clojure.lang.Compiler.eval (Compiler.java:4658)
    clojure.core/eval (core.clj:2035)
    clojure.main$repl__7403$read_eval_print__7415.invoke (main.clj:183)
    clojure.main$repl__7403.doInvoke (main.clj:200)
    clojure.lang.RestFn.invoke (RestFn.java:426)

Ответ 6

Вы не можете, если не используете пользовательскую JVM.

Когда приведение класса происходит во время выполнения, ответственность JVM заключается в создании экземпляра ClassCastException, заполнении его сообщения и его броске. В HotSpot часть построения сообщений реализована в С++; см. метод generate_class_cast_message в sharedRuntime.cpp, строка 1479 (это OpenJDK 6, код был слегка реорганизован в JDK 7, но принцип остается тем же).

Ответ 7

Поймайте его и снова отправьте его своим сообщением.

try {

} catch(ClassCastException ex) {
    throw new ClassCastException("Your own message here!");
}

Ответ 8

Clojure может быть изменен для генерации кода, который проверяет это условие, прежде чем он попытается выполнить бросок, а затем предоставит вам более информативное сообщение.