Source: Deep analysis of the enumeration types of Java--thread security and serialization issues for enumerations
Enumeration is how to ensure thread-safe
If you want to see the source code, you must first have a class, then the enumeration type is what kind of? Is that enum
right? The answer is obviously not, just enum
class
like, just a keyword, he is not a class, then what kind of enumeration is maintained by what class, we simply write an enumeration:
publicenum t { SPRING,SUMMER,AUTUMN,WINTER;}
Then we use the anti-compilation to see how this code is implemented, and the post-compilation ( Java
anti-compilation) code reads as follows:
Public Final classTextendsenum{Private T(String S,inti) {Super(s, i); } Public StaticT[]Values() {T at[];intI T at1[]; System.arraycopy(at = enum$values,0, AT1 =NewT[i = at.length],0, i);returnAT1; } Public StaticTvalueOf(String s) {returnT Enum.valueOf(demo/t, s); } Public Static FinalT SPRING; Public Static FinalT SUMMER; Public Static FinalT AUTUMN; Public Static FinalT WINTER;Private Static FinalT enum$values[];Static{SPRING =New T("SPRING",0); SUMMER =New T("SUMMER",1); AUTUMN =New T("AUTUMN",2); WINTER =New T("WINTER",3); Enum$values = (NewT[] {SPRING, SUMMER, AUTUMN, WINTER}); }}
We can see through the post-compilation code that the class inherits from the class, and the public final class T extends Enum
Enum
final
keyword tells us that the class cannot be inherited. When we use enum
to define an enumeration type, the compiler automatically helps us to create a final
class of classes that inherit the enum class, so enum types cannot be inherited, and we see several properties and methods in this class.
We can see:
Public Static FinalT SPRING; Public Static FinalT SUMMER; Public Static FinalT AUTUMN; Public Static FinalT WINTER;Private Static FinalT enum$values[];Static{SPRING =New T("SPRING",0); SUMMER =New T("SUMMER",1); AUTUMN =New T("AUTUMN",2); WINTER =New T("WINTER",3); Enum$values = (NewT[] {SPRING, SUMMER, AUTUMN, WINTER});}
Are all static
types, because static
the properties of the type are initialized after the class is loaded, and we have described in depth analysis Java's classloader mechanism (source level) and Java class loading, linking, and initializing two articles, respectively, when a Java
The first time the class is actually used, the static resources are initialized, the Java
class is loaded and the initialization process is thread-safe. Therefore, creating a enum
type is thread-safe.
Why a singleton implemented with enumerations is the best way
In the "design mode" "Creative mode" singleton mode, we see a total of six ways to implement a singleton, in which the Effective Java,
author, Josh Bloch,
advocating the use of enumerations, since the great God said this way good, then we need to know why it is good?
1. Simple enumeration notation
The simple way to do this is to look at the "design pattern" "Creative mode" in the implementation of the singleton pattern to know the difference.
publicenum EasySingleton{ INSTANCE;}
You can access it by EasySingleton.INSTANCE
coming.
2. Enumerate your own processing of serialization
We know that all the previous singleton patterns have a big problem, that is, once the interface is implemented, Serializable
it is no longer a singleton, because each call readObject()
method returns a newly created object, there is a workaround is to use the readResolve()
method to avoid this happening. However, in order to ensure that enumeration types Java
, as stated in the specification, enumerated variables that are extremely defined by each enumeration type are JVM中
unique, special provisions are made on the serialization and deserialization of enumeration types Java
. The original text reads as follows:
Enum constants is serialized differently than ordinary serializable or externalizable objects. The serialized form of an Enum constant consists solely of its name; field values of the constant is not present in the form. To serialize a enum constant, ObjectOutputStream writes the value returned by the enum constant ' s name method. To deserialize a enum constant, ObjectInputStream reads the constant name from the stream; The deserialized constant is then obtained by calling the Java.lang.Enum.valueOf method, passing the constant ' s Enum type Along with the received constant name as arguments. Like other serializable or Externalizable objects, enum constants can function as the targets of back references appearing Subsequently in the serialization stream. The process by which enum constants is serialized cannot be Customized:any class-specific writeobject, ReadObject, Reado Bjectnodata, Writereplace, and Readresolve methods defined by enum types is ignored during serialization and DESerialization. Similarly, any serialpersistentfields or serialversionuid field declarations is also ignored–all enum types have a fixeds Erialversionuid of 0L. Documenting serializable fields and data for enum types are unnecessary, since there is no variation In the type of data sent.
The
probably means that at the time of serialization Java
simply outputs the name
property of the enumeration object to the result, and deserializes it through the java.lang.Enum
The valueOf
method to find enumerated objects by name. At the same time, the compiler does not allow any customization of this serialization mechanism, so writeobject, ReadObject, Readobjectnodata, Writereplace
, and are disabled. Readresolve
and other methods. Let's take a look at this valueOf
method:
public Static <t extends enum<t>> T valueof (class<t > enumtype,string name) {T result = Enumtype. (). get (name); if (Result! = null ) return result; if (name = = null ) throw new NullPointerException ( "Name is null" ); throw new IllegalArgumentException ( "No Enum const" + enumtype + + name); }
As you can see from the code, the code tries enumType
to Class
get the enumConstantDirectory()
enumeration object named in the return from the method that called the object map
name
, and throws an exception if it does not exist. Further to the enumConstantDirectory()
method, you will find that the static method of this type will be called in a reflective manner, that is, the method that the enumType
values()
compiler created for us, and then populates the properties of the object with the returned result enumType
Class
enumConstantDirectory
.
Therefore, JVM
there is a guarantee for serialization.
3. Enumeration instance creation is thread-safe
(thread-safe)
We have described in depth analysis of Java's classloader mechanism (source level) and Java class loading, linking and initializing two articles, when a Java
class was first used, static resources are initialized, Java
The loading and initialization of classes is thread-safe. Therefore, creating a enum
type is thread-safe.
Deep analysis of Java enumeration types--thread safety and serialization issues for enumerations