With all due respect, I doubt you can enumerate in Java

Keywords: Java Database Mybatis Programming

Let's face it, enum (enumeration) is a keyword introduced in Java 1.5. It represents a special type of class. By default inherit From java.lang.Enum .

To prove this, let's create a new enumeration player type:

public enum PlayerType {
    TENNIS,
    FOOTBALL,
    BASKETBALL
}

There are two keywords with a class name, braces, and three uppercase words, but don't you see the inherited Enum class? Don't worry. You can't eat hot tofu in a hurry. Look at the decompiled bytecode with JAD, and it's clear.

public final class PlayerType extends Enum
{

    public static PlayerType[] values()
    {
        return (PlayerType[])$VALUES.clone();
    }

    public static PlayerType valueOf(String name)
    {
        return (PlayerType)Enum.valueOf(com/cmower/baeldung/enum1/PlayerType, name);
    }

    private PlayerType(String s, int i)
    {
        super(s, i);
    }

    public static final PlayerType TENNIS;
    public static final PlayerType FOOTBALL;
    public static final PlayerType BASKETBALL;
    private static final PlayerType $VALUES[];

    static 
    {
        TENNIS = new PlayerType("TENNIS", 0);
        FOOTBALL = new PlayerType("FOOTBALL", 1);
        BASKETBALL = new PlayerType("BASKETBALL", 2);
        $VALUES = (new PlayerType[] {
            TENNIS, FOOTBALL, BASKETBALL
        });
    }
}

See? The PlayerType class is final and inherits from the Enum class. We programmers didn't do the work. The compiler helped us do it quietly. In addition, it comes with several useful static methods, such as values() and valueOf(String name).

01. Internal enumeration

OK, you guys should know what the enumerator looks like, right? Since enumeration is a special class, it can be defined inside a class, so its scope can be limited to the external class.

public class Player {
    private PlayerType type;
    public enum PlayerType {
        TENNIS,
        FOOTBALL,
        BASKETBALL
    }
    
    public boolean isBasketballPlayer() {
      return getType() == PlayerType.BASKETBALL;
    }

    public PlayerType getType() {
        return type;
    }

    public void setType(PlayerType type) {
        this.type = type;
    }
}

PlayerType is the internal class of Player. The isbasketball Player () method is used to determine whether the Player is a basketball Player.

Because enumerations are final, you can ensure that there is only one constant object in the Java virtual machine (refer to the decompiled Static code block "static keyword bracketed part of the code"), so we can safely use the "= =" operator to compare whether two enumerations are equal. Refer to the isbasketball player() method.

So why not use the equals() method to judge?

if(player.getType().equals(Player.PlayerType.BASKETBALL)){};
if(player.getType() == Player.PlayerType.BASKETBALL){};

When comparing the "= =" operator, if both objects are null, NullPointerException will not occur, and the equals() method will.

In addition, the "= =" operator will be checked at compile time. If the types on both sides do not match, an error will be prompted, while the equals() method will not.

02. Enumeration can be used for switch statement

This one I wrote before what the hell As explained in detail in the article, interested partners can click the link to jump over and have a look.

switch (playerType) {
        case TENNIS:
            return "Tennis player Federer";
        case FOOTBALL:
            return "Football player C Luo";
        case BASKETBALL:
            return "Basketball player James";
        case UNKNOWN:
            throw new IllegalArgumentException("unknown");
        default:
            throw new IllegalArgumentException(
                    "Types of athletes: " + playerType);

    }

03. Enumeration can be structured

If the enumeration needs more information, you can add some fields for it, such as name in the following example. At this time, you need to add a construction method with parameters for the enumeration, so that you can add the corresponding name when defining the enumeration.

public enum PlayerType {
    TENNIS("Tennis"),
    FOOTBALL("Football"),
    BASKETBALL("Basketball");

    private String name;

    PlayerType(String name) {
        this.name = name;
    }
}

04,EnumSet

EnumSet is a special implementation class for the Set interface of enumeration type. It is a powerful tool for processing enumeration type data, and it is very efficient (the internal implementation is bit vector, which I don't understand).

Because EnumSet is an abstract class, the new keyword cannot be used when creating EnumSet. However, EnumSet provides a number of useful static factory methods:

The following example creates an EnumSet of an empty PlayerType using noneOf(); an EnumSet of all playertypes using allOf().

public class EnumSetTest {
    public enum PlayerType {
        TENNIS,
        FOOTBALL,
        BASKETBALL
    }

    public static void main(String[] args) {
        EnumSet<PlayerType> enumSetNone = EnumSet.noneOf(PlayerType.class);
        System.out.println(enumSetNone);

        EnumSet<PlayerType> enumSetAll = EnumSet.allOf(PlayerType.class);
        System.out.println(enumSetAll);
    }
}

The program output is as follows:

[]
[TENNIS, FOOTBALL, BASKETBALL]

With EnumSet, you can use some methods of Set:

05,EnumMap

EnumMap is an implementation class for Map interface of enumeration type, which can use enumeration constant as key. EnumMap is more efficient than HashMap, and you can access elements directly through array subscripts (the ordinal value of enumeration).

Unlike EnumSet, EnumMap is not an abstract class, so you can use the new keyword when creating EnumMap:

EnumMap<PlayerType, String> enumMap = new EnumMap<>(PlayerType.class);

With the EnumMap object, you can use some methods of Map:

The usage method of HashMap is roughly the same as that of HashMap. Let's see the following example:

EnumMap<PlayerType, String> enumMap = new EnumMap<>(PlayerType.class);
enumMap.put(PlayerType.BASKETBALL,"Basketball players");
enumMap.put(PlayerType.FOOTBALL,"Football player");
enumMap.put(PlayerType.TENNIS,"Tennis players");
System.out.println(enumMap);

System.out.println(enumMap.get(PlayerType.BASKETBALL));
System.out.println(enumMap.containsKey(PlayerType.BASKETBALL));
System.out.println(enumMap.remove(PlayerType.BASKETBALL));

The program output is as follows:

{TENNIS = TENNIS player, FOOTBALL = FOOTBALL player, BASKETBALL = BASKETBALL player}
Basketball players
true
 Basketball players

06. Single case

In general, it's not easy to implement a single instance. If you don't believe it, take a look at the following code

public class Singleton {  
    private volatile static Singleton singleton; 
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {
        synchronized (Singleton.class) { 
        if (singleton == null) {  
            singleton = new Singleton(); 
        }  
        }  
    }  
    return singleton;  
    }  
}

However, the emergence of enumeration reduces the amount of code to the extreme:

public enum EasySingleton{
    INSTANCE;
}

It's over. It's really super short. Do you have it? Enumeration implements the Serializable interface by default, so Java virtual machine can guarantee that the class is a single instance, which is not the same as the traditional implementation. In the traditional way, we have to make sure that the singleton cannot create any new instances during deserialization.

07. Enumeration can interact with database

We can cooperate with Mybatis to convert database fields to enumeration types. Now suppose there is a database field check_ The types of type are as follows:

`check_type` int(1) DEFAULT NULL COMMENT 'Inspection type (1: failed, 2: passed)',

Its corresponding enumeration type is CheckType, and the code is as follows:

public enum CheckType {
	NO_PASS(0, "Fail"), PASS(1, "adopt");
	private int key;

	private String text;

	private CheckType(int key, String text) {
		this.key = key;
		this.text = text;
	}

	public int getKey() {
		return key;
	}

	public String getText() {
		return text;
	}

	private static HashMap<Integer,CheckType> map = new HashMap<Integer,CheckType>();
	static {
		for(CheckType d : CheckType.values()){
			map.put(d.key, d);
		}
	}
	
	public static CheckType parse(Integer index) {
		if(map.containsKey(index)){
			return map.get(index);
		}
		return null;
	}
}

1) CheckType adds a construction method and two fields. The key is int and the text is String.

2) In CheckType, there is a public static CheckType parse(Integer index) method, which can convert an Integer to an enumeration type through key matching.

Now, we can use typeHandler in Mybatis's configuration file to convert database fields to enumeration types.

<resultMap id="CheckLog" type="com.entity.CheckLog">
  <id property="id" column="id"/>
  <result property="checkType" column="check_type" typeHandler="com.CheckTypeHandler"></result>
</resultMap>

The class corresponding to the checkType field is as follows:

public class CheckLog implements Serializable {

    private String id;
    private CheckType checkType;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public CheckType getCheckType() {
        return checkType;
    }

    public void setCheckType(CheckType checkType) {
        this.checkType = checkType;
    }
}

The source code of the CheckTypeHandler converter is as follows:

public class CheckTypeHandler extends BaseTypeHandler<CheckType> {

	@Override
	public CheckType getNullableResult(ResultSet rs, String index) throws SQLException {
		return CheckType.parse(rs.getInt(index));
	}

	@Override
	public CheckType getNullableResult(ResultSet rs, int index) throws SQLException {
		return CheckType.parse(rs.getInt(index));
	}

	@Override
	public CheckType getNullableResult(CallableStatement cs, int index) throws SQLException {
		return CheckType.parse(cs.getInt(index));
	}

	@Override
	public void setNonNullParameter(PreparedStatement ps, int index, CheckType val, JdbcType arg3) throws SQLException {
		ps.setInt(index, val.getKey());
	}
}

The core function of CheckTypeHandler is to call the parse() method of CheckType enumeration class to transform database fields.

With all due respect, after reading this article, I think my friends will definitely enumerate in Java. If not, come and chop me!

If you think this article will help you a little, please read it at the first time through wechat search "silent King II", reply "concurrent" and have a real Java Concurrent Programming battle rewritten by Alibaba Daniel, and don't worry about the interviewer's difficulties in this respect any more.

GitHub has been included in this article, Portal~ , there is a large factory interview complete test site inside, welcome Star.

I am the second king of silence, a talented programmer with a good face. Attention can improve the learning efficiency. Don't forget the three links, like, collect and leave messages. I don't pick them, hee hee.

Posted by Irvin Amoraal on Sun, 07 Jun 2020 20:17:15 -0700