Как вырвать блок инициализации? - PullRequest
0 голосов
/ 29 января 2019

У меня есть класс, похожий на этот

class Some {

    private enum Inner {
    }
}

И я пытаюсь найти класс Inner в блоке инициализации моего тестового класса.

class SomeTest {

    private static final Class<?> INNER_CLASS;

    {
        for (final Class<?> declaredClass: Some.class.getDeclaredClasses()) {
            if (declaredClass.getSimpleName().equals("Inner")) {
                INNER_CLASS = declaredClass;
                // Variable `INNER_CLASS` might be assigned in loop
                // break? return?
            }
        }
        throw new ExceptionInitializerError("failed to find Inner.class");
    }
}

компилятору это не нравится, и я не могу найти лучшего способа.

Как я могу решить эту проблему?Есть ли хороший шаблон для этого?

Ответы [ 4 ]

0 голосов
/ 29 января 2019

Есть несколько проблем с вашим кодом:

  1. У вас неверное имя исключения.Исключение, которое вы пытаетесь создать, называется ExceptionInInitializerError, а не ExceptionInitializerError.Это одна причина , почему он не будет компилироваться.

  2. Никогда 1 throw Error или подклассы Error.

  3. Если вам нужно сгенерировать непроверенное исключение, бросьте RuntimeException.Или, что еще лучше, выберите что-то более конкретное или определите и используйте свой собственный класс исключений.

  4. Это (вероятно) должен быть блок инициализатора static, а не простой (экземпляр) инициализатор.Вы хотите, чтобы этот код выполнялся один раз ... не каждый раз, когда создается экземпляр SomeTest.

  5. Выход из блока инициализации staticто, что вы хотите избежать.Это в основном оставляет вас с мертвым приложением ... потому что включающий класс и любые классы, которые зависят от него, становятся неинициализируемыми.


Сказав это, следующий может будет более подходящей структурой:

 static {
     BlahType tmp = null;
     label: {
         for (...) {
             if (...) {
                 tmp = ...;
                 break label;
             }
         }
         throw new SomeException(...);
     }
     FINAL_VAR = tmp;
}

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

И более естественный способ написать выше было бы:

static {
     BlahType tmp = null;
     for (...) {
         if (...) {
             tmp = ...;
             break;
         }
     }
     if (tmp == null) {
         throw new SomeException(...);
     }
     FINAL_VAR = tmp;
}

1- Может быть, слишком сильно.Я бы сказал, что выбрасывание AssertionError в порядке ... при условии, что вы намереваетесь , потому что его никогда не поймают / не восстановят.В этом случае восстановление в любом случае спорный.

0 голосов
/ 29 января 2019

Существует несколько проблем:

  1. Всегда генерируется исключение
  2. Вы присваиваете конечную переменную в цикле
  3. Блок инициализации не являетсяstatic и присвоение статической конечной переменной

Проверьте это:

class SomeTest {

    private static final Class<?> INNER_CLASS;

    static {
        Class<?> foundClass = null;
        for (final Class<?> declaredClass : Some.class.getDeclaredClasses()) {
            if (declaredClass.getSimpleName().equals("Inner")) {
                foundClass = declaredClass;
                // Variable `INNER_CLASS` might be assigned in loop
                // break? return?
            }
        }
        INNER_CLASS = foundClass;
        // throw new Exception("failed to find Inner.class");
    }
}
0 голосов
/ 29 января 2019

Используйте промежуточную переменную перед окончательным присвоением.

class SomeTest {

    private static final Class<?> INNER_CLASS;
    static {
        Class<?> innerClass = null;
        for (final Class<?> declaredClass: Some.class.getDeclaredClasses()) {
            if (declaredClass.getSimpleName().equals("Inner")) {
                innerClass = declaredClass;
            }
        }
        if (innerClass == null) {
            throw new ExceptionInitializerError("failed to find Inner.class");
        }
        INNER_CLASS = innerClass;
    }
}
0 голосов
/ 29 января 2019
Блок инициализации

static и instance не может генерировать отмеченные исключения, поскольку нет способа объявить, что эти блоки генерируют эти исключения.Измените ExceptionInitializerError на RuntimeException (или любой подкласс) и оберните ваш код в try-catch

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

Что касается«вырваться», ну просто ты неВы должны написать этот блок как тело метода void, но с ограничением, что вы нигде не можете использовать return.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...