Как облегчить Netbeans Designer загрузку JPanel-ов, которые используют обратный просмотр enum с использованием hashmap?

Это стало Дороти Дикс, когда я нашел корень проблемы, когда составлял этот вопрос. Тем не менее, я решил опубликовать его, потому что это поставило всех в тупик в нашем офисе, и я не смог найти ничего полезного в поисках Google или stackru. Это хороший пример того, как только вы зададите правильный вопрос, вы можете увидеть свет.

Хотя название может показаться сложным, это действительно простая проблема, на которую, похоже, нет ответа. В центре этого находится enum:

Status

    public enum Status 
    {
        INVALID     ( "INVALID"  ),
        ISSUED      ( "Issued"   ),
        CANCELLED   ( "Cancelled");

        private final   String displayName;

        private final static    Map<String,Status>    displayMap = new HashMap( 4 );


        private Status( String display  ){
            this.displayName = display;
            mapDisplayName( this.displayName, this );
        }


        public String getDisplayName(){
            return displayName;
        }

        public static Status parseString( String statusStr ) {
            return displayMap.get(  statusStr );
        }

        private static void mapDisplayName( final String displayName, final Status state ){
            displayMap.put( displayName,  state );
        }
    }

Идея, конечно же, заключается в использовании displayMap как обратный поиск. Ничего общего с getDisplayName() метод вообще.

Это перечисление getDisplayName() Вызов используется на дополнительной панели для инициализации статического массива, используемого в комбинированном окне, например:

    public class JPanelStatus extends javax.swing.JPanel { 

        private final       String[]    STATUS_LABELS = {
                                            Status.ISSUED     .getDisplayName(),
                                            Status.CANCELLED  .getDisplayName()
                                        };

        public JPanelStatus(){
            initComponents();
              :
            jComboBoxStatus.setModel( new DefaultComboBoxModel<>( STATUS_LABELS ) );
              :
        }
       :
    }

Который упоминается в основном JPanel. Когда я смотрю это JPanelStatus Подпанель в Netbeans Designer работает нормально. Как и [ Preview Design ] функция.

Однако, когда я загружаю основную форму, она терпит неудачу, и исключение показывает ошибку инициализации:

  java.lang.NoClassDefFoundError: Could not initialize class au.com.project.State
    at au.com.project.client.JPanelStatus.<init>(JPanelStatus.java:35)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
  ... ... ...

В журнал IDE Netbeans добавлена ​​следующая дополнительная информация:-p

INFO: Could not initialize class au.com.project.State

Через процесс исключения - комментирование несвязанного кода - я обнаружил, что форма будет загружаться после того, как я закомментирую HashMap put() позвонить в гос.

" Это интересно ", - говорю я. Это выглядело как побочный эффект от put(), И вдали это - маленький Спок, который быстро выдал мне ту же ошибку из командной строки без JPanel и без Netbeans.

Ошибка вызвана мной, пытаясь использовать HashMap из конструктора Enum. Это не будет работать так, как написано.

Поэтому я изменил заголовок, чтобы решить настоящую проблему - что на самом деле, как использовать HashMap для обратного поиска перечисления?

1 ответ

Проблема заключается в том, как HashMap объявляется в Status enum из-за того, как инициализируются перечисления.

Первым делом в Java Enum должен быть список значений, здесь: "INVALID", "ISSUED" и "CANCELED". Следующее, что каждый должен знать, это то, что есть секретная Java Этап, который запускается первым при создании объекта (Class или Enum). Init тупой, он проходит линейно через декларативный код первым пришел, первым обслужен.

Первые 3 x оператора перечисления вызывают конструктор - это означает:

    private final static  Map<String,Status>  displayMap = new HashMap( 4 );

Еще не был выполнен, и displayMap является нулевым Также static { } блок выполняется в той же последовательности 1-2-3-... и тоже не работает.

К сожалению, ни одна из трассировок стека NetBeans/Designer или журнала IDE не сообщила об исключении NullPointerException - модульный тест не выполняется. Когда у вас есть NPE, он фокусирует ум. displayMap не инициализируется при первом вызове конструктора.

Решение: displayMap не может быть static final потому что вы не можете инициализировать статические члены в конструкторе. Он должен быть инициализирован при первом вызове с использованием некоторого варианта показанного примера:

Status

    public enum Status
    {
        INVALID     ( "INVALID"  ),
        ISSUED      ( "Issued"   ),
        CANCELLED   ( "Cancelled");

        private static    Map<String,Status>   displayMap;

        private Status( String display  ){
            this.displayName = display;
            mapDisplayName( this.displayName, this );
        }
          :

        private static void mapDisplayName( final String displayName, final Status state ){
            if( null ==  displayMap  ){
                displayMap = new HashMap( 7 );
            }
            displayMap.put( displayName,  state );
        }
    }

И тогда все идет довольно гладко.

Предостережение:

НЕ назначать null в объявлении displayMap - это было контрпродуктивно:

  • if( null == displayMap ){...} Блок успешно назначает HashMap во время первого вызова конструктора Enum.
  • После того, как все объявления значений перечислений обработаны.
  • Init будет вызывать любые инициализации для объявленных переменных.
  • Если displayMap = null; объявляется, что он заменяет заполненный HashMap с 3-мя значениями новым пустым HashMap. гррр

Возможно связанный вопрос:

Другие вопросы по тегам