2016-06-21 2 views
2

FindBugs сообщает о моей плохой практике, findbugs:SI_INSTANCE_BEFORE_FINALS_ASSIGNED.FindBugs: статическая инициализация экземпляра в классе

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

Мой код выглядит примерно так ..

public class Foo { 

    public static final Foo DEFAULT = new Foo(Bar.A, "baz"); 

    public enum Bar { 
     A, B 
    } 

    private final Bar bar; 
    private final String baz; 

    public Foo(Bar bar, String baz) { 
     this.bar = bar; 
     this.baz = baz; 
    } 

} 

Я понимаю, что это маркировки использование new Foo в качестве статической переменной внутри Foo как плохая практика, но на самом деле не вижу проблемы.

Может кто-нибудь объяснить, почему это плохая практика, какое непреднамеренное поведение может случиться с использованием этой плохой практики и, возможно, предложить лучшую практику в качестве альтернативы?

+0

Если вы посмотрите [здесь] (https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html), в нем говорится: 'Чтобы предоставить ту же возможность для переменных класса, язык программирования Java включает в себя статические блоки инициализации. «Вы можете использовать статические блоки для создания экземпляра класса. – SomeDude

+0

@Svasa статический инициализатор не помогает. Там уже есть, неявно. –

+0

Вы уверены, что получили сообщение Findbugs для опубликованного источника? Запустив код, я получаю сообщение 'L P URF_UNREAD_FIELD UrF: Непрочитанное поле: предупреждение Foo.baz'. – Robert

ответ

1

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

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

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

+0

Это действительно хорошая точка, я могу ссылаться на статику из конструктора. Удивленный, он не дает некоторого бесконечного цикла рекурсии. Спасибо Энди! –

 Смежные вопросы

  • Нет связанных вопросов^_^