Предисловие
В Java объект должен быть правильно инициализирован, прежде чем его можно будет использовать, что предусмотрено спецификацией Java. Недавно я обнаружил интересный вопрос, и ответ на этот вопрос обманул мои глаза на первый взгляд. Взгляните на эти три категории:
пакет com.ds.test; public class overs {string upperstring; public overs () {initializer.initialize (this); }} пакет com.ds.test; public class lower extends overs {string lowerstring = null; public lower () {super (); System.out.println ("Upper:" + upperstring); System.out.println ("Lower:" + lowerstring); } public static void main (final String [] args) {new Lower (); }} пакет com.ds.test; public class initializer {static void инициализировать (окончательный верхний anupper) {if (anupper instanceof lower) {нижний нижний = (нижний) anupper; Lower.LowerString = "Lowerinited"; } anupper.upperstring = "upperinited"; }} Какой выход можно получить с помощью Lower класса? В этом минимальном примере всю ситуацию можно увидеть легче, но эта ситуация происходит в действительности, и будет много кода, отвлекая человека.
В любом случае, вывод такой:
Верхний: UpperinitedLower: NULL;
Хотя тип String используется в небольшом примере, фактический код класса Initializer имеет объект делегата для регистрации, который такой же, как и функция Lower класса - по крайней мере, Lower класс является намерением. Но по какой -то причине это не работает при запуске приложения. Вместо этого используется путь по умолчанию, и объект делегата не установлен (NULL).
Теперь немного измените код Lower :
пакет com.ds.test; public class lower extends overs {string lowerstring; public lower () {super (); System.out.println ("Upper:" + upperstring); System.out.println ("Lower:" + lowerstring); } public static void main (final String [] args) {new Lower (); }}Вывод теперь выглядит так:
Верхний: UpperinitedLower: Lowerinited
Вы нашли разницу в коде?
Да, это поле lowerString больше не подходит для пустоты. Почему это отличается? В любом случае, разве значение по умолчанию поля типа ссылки (например, String здесь) не пусто? Конечно, это пусто. Оказывается, что, хотя это небольшое изменение, очевидно, не изменяет поведение кода каким -либо образом, оно отличает результат.
Итак, что именно произошло? Все становится ясным при проверке порядка инициализации:
1. Функция main() вызывает Lower конструктор.
2. Пример Lower готов. Это означает, что все поля создаются и заполнены значениями по умолчанию, например, значение по умолчанию типа эталона пустое, а значение логического типа по умолчанию является false . В настоящее время не происходит встроенного назначения на поле.
3. Конструктор родительского класса называется. Это обеспечивается характеристиками языка. Так что, прежде чем что -либо еще происходит, конструктор Апп -конструктор называется.
4. Обратите внимание на этот конструктор запускает и определяет ссылку на недавно созданный экземпляр метода Initializer.initialize() .
5. Класс Initializer прикрепляет новую строку к двум полям ( upperString и lowerString ). Присвоение значений этим двум полям, используя немного грязного instanceof проверки экземпляров, не является особенно хорошим шаблоном дизайна, но он также работает, не беспокойтесь об этом. Как только это произойдет, ссылки на upperString и lowerString более не пусты.
6. Призыв к Initializer.initialize() завершен, а Upper конструктор также завершен.
7. Теперь это становится интересным: строительство Lower экземпляра продолжается. Предполагая, что =null назначение явно не указано в объявлении поля lowerString , Lower конструктор возобновляет выполнение и распечатывает две строки, подключенные к поле.
Однако, если есть операция, которая явно присваивает NULL, процесс выполнения будет немного отличаться: когда конструктор родительского класса будет завершен, любая инициализация переменной будет выполнена до работы остальных конструкторов (см. Раздел 12.5 спецификации языка Java). В этом случае ссылка на строку, назначенную ранее lowerString , не присваивается NULL. Затем продолжайте выполнять оставшуюся построение функции, и теперь печатайте значение lowerString в качестве: null.
Это отличный пример, не только для того, чтобы облегчить наше внимание к некоторым подробностям о создании объектов (или для того, чтобы узнать, где проверить спецификации кодирования Java, напечатанные или онлайн), но и показать, почему написание подобных инициализаций является плохим. Мы вообще не должны заботиться о подклассе Upper. И наоборот, если по какой -то причине инициализация определенных полей не может быть сделана в самом подклассе, она потребует только некоторых вариантов своего собственного класса Helper инициализации. В этом случае, если вы используете String lowString или String lowerString = null на самом деле нет разницы, какая она должна быть.
Суммировать
Вышеуказанное - все содержание этой статьи. Я надеюсь, что содержание этой статьи поможет для каждого обучения или работы каждого. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения.