Данное диагностическое правило выявляет случаи неправильного порядка объявления статических полей внутри класса, а также случаи зависимостей статических полей от других классов. Такие случаи могут привести к сложному поддержанию кода или к ошибочной инициализации класса.
Случай 1.
Использование статического поля до того, как оно будет проинициализировано.
Рассмотрим синтетический пример некорректного кода:
public class Purse { static private Purse reserve = new Purse(10); static private int scale = 5 + (int) (Math.random() * 5); private int deposit; Purse() { deposit = 0; } Purse(int initial) { deposit = initial * scale; } ... }
Как известно, статические поля будут инициализироваться в порядке объявления самыми первыми при первом использовании класса. Следовательно, в данном примере сначала инициализируется 'reserve', а потом 'scale'.
Рассмотрим инициализацию статического поля 'reserve':
Вследствие чего, поле 'deposit' у объекта 'reserve' будет проинициализировано не так, как задумывалось.
Для того, чтобы исправить ситуацию, необходимо поменять порядок объявления статических полей:
public class Purse { static private int scale = 5 + (int) (Math.random() * 5); static private Purse reserve = new Purse(10); private int deposit; Purse() { deposit = 0; } Purse(int initial) { deposit = initial * scale; } ... }
Случай 2.
Взаимная зависимость статических полей разных классов.
Рассмотрим синтетический пример некорректного кода:
public class A { public static int scheduleWeeks = B.scheduleDays / 7 + 1; .... } .... public class B { public static int scheduleDays = A.scheduleWeeks * 7 + 7; .... }
Ситуация здесь такова, что статическое поле 'A.scheduleWeeks' зависит от статического поля 'B.scheduleDays', и наоборот. Порядок инициализации классов может меняться, отсюда меняется и порядок инициализации статических полей. Если инициализируется первым класс 'A', то 'A.scheduleWeeks' будет иметь значение 2, а 'B.scheduleDays' – 7. Если первым будет класс 'B', то 'A.scheduleWeeks' будет равен 1, а 'B.scheduleDays' – 14. Вряд ли такое поведение будет приятно наблюдать у себя в коде. В таком случае необходимо пересмотреть инициализацию этих полей и убрать зависимость друг от друга.
Например, можно одно из статических полей инициализировать константой, и эта зависимость исчезнет:
public class A { public static int scheduleWeeks = B.scheduleDays / 7 + 1; .... } .... public class B { public static int scheduleDays = 14; .... }
В таком случае 'B.scheduleDays' всегда будет равен 14, а 'A.scheduleWeeks' – 3.
Случай 3.
Инициализация статического поля в одном классе, используя статический метод второго класса, который в свою очередь использует статический метод или поле первого класса.
Рассмотрим синтетический пример некорректного кода:
public class A { public static int scheduleWeeks = B.getScheduleWeeks(); public static int getScheduleDays() { return 21; } .... } .... public class B { public static int getScheduleWeeks() {return A.getScheduleDays()/7;} .... }
Независимо от того, какой из классов первым будет инициализирован, поле 'A.scheduleWeeks' примет значение равное 3. Несмотря на это, такой способ инициализации сбивает с толку при чтении и поддержке такого кода.
Например, можно подкорректировать код следующим образом:
public class A { public static int scheduleWeeks = B.getScheduleWeeks(); .... } .... public class B { public static int getScheduleDays() { return 21; } public static int getScheduleWeeks() {return B.getScheduleDays()/7;} }
Данная диагностика классифицируется как:
|
Взгляните на примеры ошибок, обнаруженных с помощью диагностики V6050. |