An in-depth analysis of enum enum in Java

Source: Internet
Author: User

Tags: autumn directive net Lang Man set unbox map Gradle

In programming languages, we are exposed to enum types, and we usually have poor enumerations to implement some limitations. Java is no exception. The enumeration type in Java is enum, and this article provides some more in-depth analysis of enumerations.

What is an enum

Enum is an attribute introduced from Java 5 to facilitate the implementation of enumeration applications by Java developers. A simple enum is used as follows.

Colorenum.java
public enum Coloremun {
RED,
GREEN,
YELLOW
}

public void Setcolorenum (Coloremun colorenum) {
Some code here
}

Setcolorenum (Coloremun.green);
Why would there be an enum?

Before the enum, we used code like this to implement the enumeration functionality.

public static final int color_red = 0;
public static final int color_green = 1;
public static final int color_yellow = 2;

public void SetColor (int color) {
Some code here
}
Call
SetColor (color_red)
But there's still a perfect place on top.

SetColor (color_red) works the same as SetColor (0), while the latter is poorly readable but works
The SetColor method can accept values other than enumerations, such as SetColor (3), in which case the program may have problems
In summary, the traditional enumeration has the following two drawbacks

Security
Readability, especially when printing logs
So Java introduces an enum, and with Enum, it's easy to implement the enumeration above, and it's easy to avoid the risk of passing in illegal values.

What is the enumeration principle?

The essence of enum in Java is actually converted to the corresponding class form at compile time.

First of all, in order to explore the principle of enumeration, we first define an enumeration class, here in the season as an example, the class name is season, including the spring and autumn four enumeration entries.

public enum Season {
SPRING,
SUMMER,
AUTUMN,
WINTER
}
Then we use Javac to compile the above class and get the class file.

Javac Season.java
Then, we use the anti-compilation method to see what the bytecode file is. The tool used here is a simple command of JAVAP, listing all the elements under this season.

Company JAVAP Season
Warning:binary file Season contains Com.company.Season
Compiled from "Season.java"
Public final class Com.company.Season extends Java.lang.enum<com.company.season> {
public static final Com.company.Season SPRING;
public static final Com.company.Season SUMMER;
public static final Com.company.Season AUTUMN;
public static final Com.company.Season WINTER;
public static com.company.season[] values ();
public static Com.company.Season valueOf (java.lang.String);
static {};
}
From the top anti-compilation results

The season in the Java code is converted to the class of the Java.lang.enum inherited from
Since implicitly inheriting from Java.lang.enum, it means that in Java code, season can no longer inherit other classes
Season is marked as final, meaning it cannot be inherited.
Static code block

Using JAVAP to specifically decompile the class file, get the static code block related results as

static {};
Code:
0:new #4//Class Com/company/season
3:dup
4:LDC #7//String SPRING
6:iconst_0
7:invokespecial #8//Method "<init>":(ljava/lang/string;i) V
10:putstatic #9//Field Spring:lcom/company/season;
13:new #4//Class Com/company/season
16:dup
17:LDC #10//String SUMMER
19:iconst_1
20:invokespecial #8//Method "<init>":(ljava/lang/string;i) V
23:putstatic #11//Field Summer:lcom/company/season;
26:new #4//Class Com/company/season
29:dup
30:LDC #12//String AUTUMN
32:iconst_2
33:invokespecial #8//Method "<init>":(ljava/lang/string;i) V
36:putstatic #13//Field Autumn:lcom/company/season;
39:new #4//Class Com/company/season
42:dup
43:LDC #14//String WINTER
45:iconst_3
46:invokespecial #8//Method "<init>":(ljava/lang/string;i) V
49:putstatic #15//Field Winter:lcom/company/season;
52:iconst_4
53:anewarray #4//Class Com/company/season
56:dup
57:iconst_0
58:getstatic #9//Field Spring:lcom/company/season;
61:aastore
62:dup
63:iconst_1
64:getstatic #11//Field Summer:lcom/company/season;
67:aastore
68:dup
69:iconst_2
70:getstatic #13//Field Autumn:lcom/company/season;
73:aastore
74:dup
75:iconst_3
76:getstatic #15//Field Winter:lcom/company/season;
79:aastore
80:putstatic #1//Field $VALUES: [Lcom/company/season;
83:return
}
which

0~52 for instantiation of Spring, SUMMER, AUTUMN, WINTER
53~83 to create the season[] array $values, and put the above four objects into an array of operations.
Values method

The return value of the values method is actually the $values array object above

Enumeration in the Swtich

In Java, Switch-case is a Process control statement that we often use. After the quote came, Switch-case also very good support.

For example, the following code is completely normal compile, normal operation.

public static void Main (string[] args) {
Season Season = season.spring;
Switch (season) {
Case SPRING:
System.out.println ("It ' s Spring");
Break

Case WINTER:
System.out.println ("It ' s Winter");
Break

Case SUMMER:
System.out.println ("It ' s Summer");
Break
Case AUTUMN:
System.out.println ("It ' s Autumn");
Break
}
}
However, normally switch-case supports types like int, so how does it support enum, and we decompile the above method to see the real situation of the bytecode.

public static void Main (java.lang.string[]);
Code:
0:getstatic #2//Field Com/company/season.spring:lcom/company/season;
3:astore_1
4:getstatic #3//Field com/company/main$1. $SwitchMap $com$company$season:[i
7:aload_1
8:invokevirtual #4//Method com/company/season.ordinal: () I
11:iaload
12:tableswitch {//1 to 4
1:44
2:55
3:66
4:77
Default:85
}
44:getstatic #5//Field Java/lang/system.out:ljava/io/printstream;
47:LDC #6//String It ' s Spring
49:invokevirtual #7//Method java/io/printstream.println: (ljava/lang/string;) V
52:goto 85
55:getstatic #5//Field Java/lang/system.out:ljava/io/printstream;
58:LDC #8//String It ' s Winter
60:invokevirtual #7//Method java/io/printstream.println: (ljava/lang/string;) V
63:goto 85
66:getstatic #5//Field Java/lang/system.out:ljava/io/printstream;
69:LDC #9//String It ' s Summer
71:invokevirtual #7//Method java/io/printstream.println: (ljava/lang/string;) V
74:goto 85
77:getstatic #5//Field Java/lang/system.out:ljava/io/printstream;
80:LDC #10//String It ' s Autumn
82:invokevirtual #7//Method java/io/printstream.println: (ljava/lang/string;) V
88:return
Note that the code block above has such a piece of code

8:invokevirtual #4//Method com/company/season.ordinal: () I
The fact is, in Switch-case, the enum is converted to an int value (by calling the Enum.oridinal () method)

Enumeration and confusion

In Android development, confusion is an essential part of our pre-release work, and we can increase the difficulty of anti-compilation and, to a certain extent, protect the enhanced security.

And developers are dealing with confusion more by adding some elements to a non-confusing list, where enumerations need to be excluded from confusion.

In the default obfuscation configuration file, the handling of enumeration obfuscation has been added

# for enumeration classes, see Http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
public static **[] values ();
public static * * VALUEOF (java.lang.String);
}
For information on why you should keep the values () method and the ValueOf () method, please refer to the article reading the code in Android to confuse the part about enumerations

Using Proguard optimization

Using Proguard for optimization, you can convert an enumeration to an int as much as possible. Configured as follows

-optimizations Class/unboxing/enum
Make sure that the code above takes effect and requires that the Proguard configuration file does not contain the-dontoptimize directive.

When we use Gradlew packaging is, see output similar to the following, Urumqi Lou Feng is the number of the unboxed enum CLASSES:1 represents an enumeration has been converted into the form of int.

Optimizing ...
Number of finalized classes:0 (disabled)
Number of unboxed enum classes:1
Number of vertically merged classes:0 (disabled)
Number of horizontally merged classes:0 (disabled)
Enumeration single Example

The singleton pattern is the most commonly used design pattern in our daily development.

Then we should design a single-case model, just consider a few points

Make sure there are only unique instances and don't create more redundant instances
Make sure that the instance is created on demand.
So the traditional way to achieve a single case, roughly a few

A hungry man-load
Lazy-Synchronize and double-check
Using the static loading mechanism of Java
Using enumerations can also be used to implement a singleton, and it is simpler than the above method.

public enum AppManager {
INSTANCE;

Private String TagName;
public void Settag (String tagName) {
This.tagname = TagName;
}

Public String Gettag () {
return tagName;
}
}
It's easier to call.

AppManager.INSTANCE.getTag ();
Enumeration how to ensure unique instances

Because obtaining an instance can only be achieved by appmanager.instance

The following way is not possible

AppManager AppManager = new AppManager (); Compile error
For a singleton pattern, you can read more about this design pattern in a single example.

should not use enumerations (in Android)

Now that the enumeration is converted into a class, this theoretically causes the following problem

Increase the size of the Dex package, theoretically the larger the Dex package, the slower the loading speed
Using enumerations at the same time, the memory footprint of the runtime is also relatively large
On the above two points of verification, autumn million has done a detailed argument, Urumqi Lou Feng www.jsgren.com You can refer to this article "How much memory Enum in Android?" How to use it? 》

For the conclusion that enumeration is used, you can refer to

If you are developing a framework that does not recommend using enum
If it is a simple enum, you can easily replace it with int, it is not recommended to use enum
In addition, if it is Android, you can use the enumeration annotations described below to implement it.
In addition to this, we need to compare readability and maintainability to measure with performance, and make a compromise from it.
An alternative in Android

The newly introduced alternative enumeration annotations in Android are Intdef and Stringdef, which are illustrated here with Intdef as an example.

public class Colors {
@IntDef ({RED, GREEN, YELLOW})
@Retention (Retentionpolicy.source)
Public @interface lightcolors{}

public static final int RED = 0;
public static final int GREEN = 1;
public static final int YELLOW = 2;
}
declaring the necessary int constants
Declare an annotation as Lightcolors
With @intdef decorated lightcolors, the parameter is set to the collection to be enumerated
Use @retention (retentionpolicy.source) to specify that annotations exist only with the source code and are not added to the class file
For example, the parameters we use to label methods

private void SetColor (@Colors. lightcolors int color) {
LOG.D ("Mainactivity", "setcolor color=" + color);
}
Called when the method is

SetColor (Colors.green);
For an enumeration in Android, you can refer to the annotations in Android

These are some of my in-depth analysis of the enum in Java, Welcome to enlighten us.

An in-depth analysis of enum enum in Java

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

Tags Index: