Абстрактный класс внутри использования статического блока
Я могу добавить абстрактное ключевое слово внутри статического блока инициализации, но не могу добавить абстрактный метод как
abstract void draw();
Поэтому я могу добавить только абстрактный класс внутри статического блока, как показано ниже:
static {
abstract class Abstract {
abstract String test();
}
class Extends extends Abstract {
@Override
String test() {
return null;
}
}
new Extends().test();
Но нереально добавлять иерархию классов внутри статического блока, который будет иметь более низкий уровень доступа, чем приватный, есть ли другое использование abstract
внутри статического блока?
1 ответ
TL;DR Там нет вменяемого использования для этой функции. Если бы я увидел это в обзоре кода, я бы заставил автора провести его рефакторинг.
Иногда спецификация Java позволяет вам писать вещи, которые вы не должны делать в нормальном рабочем коде, и для меня это один из примеров.
Давайте попробуем вывести фрагмент кода, который использует эту функцию.
Нам разрешено использовать abstract
ключевое слово в статическом блоке инициализации. Это можно сделать только при определении класса, объявив сам класс abstract
и, возможно, некоторые из его методов.
Этот класс не виден за пределами блока инициализации, поэтому мы можем сделать вывод, что будем использовать его внутри. abstract
это все о создании экземпляров или определения методов экземпляров. Таким образом, это полезно, только если мы планируем создавать экземпляры абстрактного класса.
Теперь класс является абстрактным, поэтому для создания экземпляров нам нужен как минимум один подкласс.
Если у нас есть только один подкласс, зачем разделять его функциональность на абстрактный родительский и один дочерний класс? Это было бы излишне сложно, поэтому мы можем предположить, что у нас есть несколько дочерних классов.
Таким образом, для любого (по крайней мере полусмысленного) использования abstract
ключевое слово внутри статического блока инициализации, этот блок должен определять один абстрактный родительский класс, несколько дочерних классов, а также код, который создает экземпляры этих классов, как в следующем минимальном примере:
static private int value;
static {
abstract class Abstract {
abstract int method1();
}
class Child1 extends Abstract {
int method1() {
return 1;
}
}
class Child2 extends Abstract {
int method1() {
return 2;
}
}
Abstract instance1 = new Child1();
Abstract instance2 = new Child2();
value = instance1.method1() + instance2.method1();
}
ИМХО, использование статического инициализатора вообще должно быть исключением, и такой монстр требует рефакторинга, например, перемещая классы из блока инициализации, чтобы стать обычными вложенными классами, или, что еще лучше, перемещая их в свои собственные файлы.
Единственный аспект этого шаблона abstract-in-initializer, отличающийся от измененных версий, - это видимость класса. Вы получаете видимость, ограниченную только внутри static { ... }
блок. Но если ваш класс настолько сложный и длинный, что вы боитесь неправильного использования вне вашего static { ... }
блок, ты все равно проиграл...