UTC should be a class#306
UTC should be a class#306xiangyushawn merged 1 commit intomicrosoft:devfrom marschall:utc-class-instead-of-enum
Conversation
Codecov Report
@@ Coverage Diff @@
## dev #306 +/- ##
============================================
- Coverage 37.33% 37.25% -0.09%
+ Complexity 1669 1667 -2
============================================
Files 103 103
Lines 23667 23667
Branches 3880 3880
============================================
- Hits 8835 8816 -19
- Misses 13239 13260 +21
+ Partials 1593 1591 -2
Continue to review full report at Codecov.
|
|
Hello @marschall , thank you for your findings and knowledge sharing. However, I created a sample program and it seems like Enum does delay the initialization of the variable.. The following is my sample program.. could you please tell me what I do wrong? Thank you! |
|
Indeed class loading is delayed until the variable is accessed. |
|
Sorry for closing too early Consider the following example public class DemonstraceEnumInitialization {
public static void main(String[] args) throws InterruptedException {
System.out.println("not accessing constants");
TimeZone tz;
tz = 1 < 2 ? null : UtcEnum.timeZone;
System.out.println(tz);
tz = 1 < 2 ? null : UtcClass.timeZone;
System.out.println(tz);
System.out.println("accessing constants");
System.out.println(UtcEnum.timeZone);
System.out.println(UtcClass.timeZone);
}
}
enum UtcEnum {
INSTANCE;
static final TimeZone timeZone = utcTimeZone();
private static TimeZone utcTimeZone() {
System.out.println("UtcEnum.utcTimeZone()");
return new SimpleTimeZone(0, "UTC");
}
}
class UtcClass {
static final TimeZone timeZone = utcTimeZone();
private static TimeZone utcTimeZone() {
System.out.println("UtcClass.utcTimeZone()");
return new SimpleTimeZone(0, "UTC");
}
}The output is: What we see is
|
|
Hello @marschall thank you for your sharing. I also noticed, for static variable, there was no difference between enum or class in term of initialization delay. My opinion was leaving it as is since there is no difference in behaviour or error caused by it. However, if there is any reason that we should use class over enum, please share with us. Then we can change it after testing in our test lab. Thank you! |
|
Also, there is one more reason I prefer enum over class. Demonstrated by the following code: output is: For class, it is possible to call the constructor. Once constructor is called, the static variable is initialized. With enum, we can make sure the variable is initialized only when it is called explicitly. What do you think? |
While it is true that the enum prevents calling the constructor it does not prevent using the enum constant. Using the enum constant initializes the class just like calling the constructor. If you change the code to use the enum constant it behaves the same way as with a constructor public class DemonstrateEnumInitialization {
public static void main(String[] args) throws InterruptedException {
System.out.println("not accessing constants");
Long tz;
tz = 1 < 2 ? null : UtcEnum.longV;
System.out.println(tz);
tz = 1 < 2 ? null : UtcClass.longV;
System.out.println(tz);
UtcEnum utc = UtcEnum.INSTANCE;
System.out.println("accessing constants");
Thread.sleep(3000);
System.out.println(UtcEnum.longV);
System.out.println(UtcClass.longV);
}
}
enum UtcEnum {
INSTANCE;
static Long longV = System.currentTimeMillis();
}
class UtcClass {
static Long longV = System.currentTimeMillis();
}I would add four things
|
UTC is an enum with one constant and a static variable. It has the
following comment
> The enum type delays initialization until first use.
This is demonstrably wrong.
The static variable is initialized when the class is initialized. If we
look at the decompiled static initializer of UTC we see that.
```
// access flags 0x8
static <clinit>()V
L0
LINENUMBER 522 L0
NEW com/microsoft/sqlserver/jdbc/UTC
DUP
LDC "INSTANCE"
ICONST_0
INVOKESPECIAL com/microsoft/sqlserver/jdbc/UTC.<init> (Ljava/lang/String;I)V
PUTSTATIC com/microsoft/sqlserver/jdbc/UTC.INSTANCE : Lcom/microsoft/sqlserver/jdbc/UTC;
ICONST_1
ANEWARRAY com/microsoft/sqlserver/jdbc/UTC
DUP
ICONST_0
GETSTATIC com/microsoft/sqlserver/jdbc/UTC.INSTANCE : Lcom/microsoft/sqlserver/jdbc/UTC;
AASTORE
PUTSTATIC com/microsoft/sqlserver/jdbc/UTC.ENUM$VALUES : [Lcom/microsoft/sqlserver/jdbc/UTC;
L1
LINENUMBER 524 L1
NEW java/util/SimpleTimeZone
DUP
ICONST_0
LDC "UTC"
INVOKESPECIAL java/util/SimpleTimeZone.<init> (ILjava/lang/String;)V
PUTSTATIC com/microsoft/sqlserver/jdbc/UTC.timeZone : Ljava/util/TimeZone;
RETURN
MAXSTACK = 4
MAXLOCALS = 0
```
|
Hello @marschall Thank you for your reply. I am convinced by point 3
This definitely addresses my concern. I am going to test the changes and merge it once test is done. Thank you very much for your sharing and explanation. |
UTC is an enum with one constant and a static variable. It has the
following comment
This is demonstrably wrong.
The static variable is initialized when the class is initialized. If we
look at the decompiled static initializer of UTC we see that.