V6050. Class initialization cycle is present.
This diagnostic detects cases of incorrect declaration order of static class fields, as well as cases where static fields depend on other classes. Such defects make the code hard to maintain or result in incorrect class initialization.
Case 1.
Using a static field before it gets initialized.
Consider the following artificial example:
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;
}
...
}
As you know, when a class is used for the first time, static fields are the first to be initialized and they are initialized in the order in which they are declared. So, in this example, 'reserve' is initialized first, and 'scale' is initialized after that.
This is how the static field 'reserve' is initialized:
- The 'Purse' constructor is called with the argument 'initial = 10'.
- While evaluating the 'initial * scale' expression in this constructor, the field 'scale' is not yet initialized and has the default value (0) rather than the value within the range [5;10].
As a result, the 'deposit' field of the object 'reserve' will not be initialized in the desired way.
To fix this, we need to change the declaration order of the static fields:
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;
}
...
}
Case 2.
Mutual dependence of static fields of different classes.
Consider the following artificial example:
public class A {
public static int scheduleWeeks = B.scheduleDays / 7 + 1;
....
}
....
public class B {
public static int scheduleDays = A.scheduleWeeks * 7 + 7;
....
}
The static field 'A.scheduleWeeks' depends on the static field 'B.scheduleDays', and vice versa. The classes may get initialized in one order or another, and so may the static fields. If the 'A' class is initialized first, then 'A.scheduleWeeks' will refer to the value 2 and 'B.scheduleDays', the value 7. If the 'B' class is initialized first, then 'A.scheduleWeeks' will refer to the value 1 and 'B.scheduleDays', the value 14. This is not the way programmers would like their code to behave. To fix the defect, we should revise how the fields are initialized to remove their mutual dependence.
For example, initializing one of the static fields to a constant would make them no longer dependent on each other:
public class A {
public static int scheduleWeeks = B.scheduleDays / 7 + 1;
....
}
....
public class B {
public static int scheduleDays = 14;
....
}
With this fix, 'B.scheduleDays' will always refer to 14 and 'A.scheduleWeeks' to 3.
Case 3.
A static field of one class is initialized by a static method of another class, and that method, in its turn, uses a static method or field of the first class.
Consider the following artificial example:
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;}
....
}
No matter which of the classes is initialized first, the field 'A.scheduleWeeks' will be assigned the value 3. Even so, initializing fields in a way like that makes the code hard to read and maintain.
This snippet could be fixed in the following way:
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;}
}
This diagnostic is classified as:
|
You can look at examples of errors detected by the V6050 diagnostic. |