Name: tb29552 Date: 08/12/97
Dear People,
I'm not 100% sure that the behavior I'm going to describe
is not intentional, but just in case, here are the details.
I have created a class that represents an enumerated type Color
The class defines a number of public static final Color objects
that represent various Colors. On top of that, there are two class
variables: head and tail, that reference the first and the last
defined constant. Creating a new Color object changes the values
of head and tail. How the change is seen outside depends on the order
of lines in the source code. This strikes me as a bit odd and hence
this message.
Here is the full code of the Color class
public final class Color {
// moving this one changes nothing
private static int count = 0; // counter for Colors
// THESE LINES MAY CAUSE DIFFEREN BEHAVIOR
private static Color head = null; // the first constant
private static Color tail = null; // the last constant
//////////////////////////////////////////////
// public constants of the enumerated type //
//////////////////////////////////////////////
public static final Color RED = new Color( "Red" );
public static final Color BLUE = new Color( "Blue" );
public static final Color BLACK = new Color( "Black" );
public static final Color PINK = new Color( "Pink" );
// .. etc. and so on
public static final Color GREEN = new Color( "Green" );
/**
* maps the enumerated constant to an integer. Can be used to
* access arrays, as in Color x = Color.BLUE; ... c[x.ord] = 1;
**/
public final int ord;
/**
* Returns a textual representation of the enumerated constant.
**/
public String toString() { return this.name; }
/**
* returns the constant that follows this one.
**/
public Color pred() { return this.prev; }
/**
* returns the constant that preceds this one.
**/
public Color succ() { return this.next; }
/**
* returns the number of constants defined for this enumeration.
**/
public static int size() { return count; }
/**
* return the first constant in the enumeration.
**/
public static Color first() { return head; }
/**
* returns the last constant in the enumeration.
**/
public static Color last() { return tail; }
/////////////////////////////////////////////////
// private parts
/////////////////////////////////////////////////
private Color( String id ) {
name = id;
ord = count++;
if( head == null )
head = this;
if( tail != null ) {
this.prev = tail;
tail.next = this;
}
tail = this;
}/* Color */
private String name; // name of the constant
private Color prev; // preceding Color
private Color next; // the color that follows
}/* class Color */
In the code above a number (2) of lines is marked as
THESE LINES MAY CAUSE DIFFERET BEHAVIOR. If you move
them below lines that introduce RED, BLUE, etc. the
functionality of the class is broken. What happens is
that if Color constant are declared first followed by
private static constants, the Color constants will be
created, modifying private constants, but then the last
4 or so instruction of the static{} block will reset
head and tail to null. Surprisingly, they do not reset
count, which remains at 5. Thus moving count around
has no impact on the program behavior, but moving
declarations of head and tail does. This, like I said,
can be perceived as anomally. The reason I have came
across the above is because I tend to place private
members at the bottom of the class and public at the top.
Clearly, in this case, it leads to undesired effects.
While it is difficult to avoid interdependecies between
static variables, I would think that they would affect
ALL static varibles, count included. However, this is not
the case.
company - University of Newcastle , email - ###@###.###
======================================================================
- duplicates
-
JDK-1227855 Ill-defined order of initialization.
- Closed