What is the difference between enumeration and interface constants and class constants?

a simple need

During our actual development of the java project, one day the "Leader Wang" suddenly gave a task. The company's system needs to support the needs of commodity management. For example, fruits include: apples, bananas, grapes, etc. Electronic products include: computers, mobile phones
, camera etc.

We generally create new product categories Goods:

public class Goods {
    /**
     * 商品名称
     */
    private String name;
    /**
     * 商品类型
     */
    private Integer type;

    public Goods(String name, Integer type) {
        this.name = name;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getType() {
        return type;
    }

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

Then we can use it directly:

public class GoodsTest {
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods("水果",1);//1代表苹果,2:香蕉,3:葡萄
        System.out.println(goods.getName());
    }
}

But there is a problem, the business code is not clear, sometimes the developers do not know 1、2、3what it means, and it is very dangerous to directly write numbers or strings in the business code layer, we need a solution that can not only Putting the state and type together can limit the input value of the class and improve the security of the project

interface constant

We can use interface constants to solve the above problem

public interface StatusContentFace {
    public static final String fruit  = "fruit";

    public static final Integer apple  = 1;

    public static final Integer banana  = 2;

    public static final Integer grape  = 3;

    //==========================

    public static final String eleProduct  = "eleProduct";

    public static final Integer computer  = 101;

    public static final Integer phone  = 102;

    public static final Integer camera  = 103;
}

Let's look at the test class again:

public class GoodsTest1 {
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods(StatusContentFace.fruit,StatusContentFace.apple);
        Goods goods_2 = new Goods(StatusContentFace.eleProduct,StatusContentFace.computer);
        System.out.println(goods.getName());
        System.out.println(goods_2.getName());
    }
}

This allows related constants to be in the same interface file. Interface constants are more concise to write, but in order to let others know the meaning of each constant, it is best to write comments.
But it has a problem at the same time, because the interface in java supports multiple inheritance

  • We can go deep into its implementation class code, which is obviously unreasonable for a constant class interface.
  • We can also continue to add constants in its sub-interfaces, so that all constants cannot be controlled in the ancestor interface, which is undoubtedly very dangerous.

Generally not recommended, but interface constants are not useless, you can 内部接口achieve 分组the effect by

public class GoodsTest2 {
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods(Fruit.type,Fruit.banana);
        Goods goods_2 = new Goods(EleProduct.type,EleProduct.phone);
        System.out.println(goods.getName());
        System.out.println(goods_2.getName());
    }
    
    //常量分组
    public interface Fruit {
        String type = "fruit";
        Integer apple = 1;
        Integer banana = 2;
        Integer grape = 3;
    }

    public interface EleProduct {
        String type = "eleProduct";
        Integer computer = 101;
        Integer phone = 102;
        Integer camera = 103;
    }
    
}

In this way, we can group related constants into one category, which is more concise and clear.

class constant

We generally use 类常量the method:

public final class StatusConstant {
    private StatusConstant() {} //防止该类实例化

    public static final String fruit  = "fruit";

    public static final Integer apple  = 1;

    public static final Integer banana  = 2;

    public static final Integer grape  = 3;

    //==========================

    public static final String eleProduct  = "eleProduct";

    public static final Integer computer  = 101;

    public static final Integer phone  = 102;

    public static final Integer camera  = 103;
}

Note: generally use the final keyword to modify the class to prevent it from being inherited, and make its constructor private to prevent it from being instantiated

Test class:

public class GoodsTest3 {
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods(StatusConstant.fruit, StatusConstant.banana);
        Goods goods_2 = new Goods(StatusConstant.eleProduct, StatusConstant.phone);
        System.out.println(goods.getName());
        System.out.println(goods_2.getName());
    }
}

The way we can find 类常量is indeed very convenient, and there is no 多继承trouble with interface constants. But the information she can undertake is not dimensionally enough, and it can only undertake information in one field. However, when the project is complex, we hope that it can often undertake information of more dimensions, similar to objects, with more attributes

{
    "name": ...,
    "type": ...,
     ... 
}

At this time, the protagonist of our article, the enumeration, will make its debut!

enumerate

What are enums?

Enumeration is a special class. All enumeration classes are subclasses of Enum class, just like Object class. Since java class is single inheritance, it cannot inherit other classes or enumerations.
Enumeration variables cannot use other data, only constants in the enumeration can be used for assignment. It can improve the security of the program .

Format:

public enum 枚举名{ 
  //枚举的取值范围 
} 

enumeration constant

We first define an enumeration class to define constants:

public enum ContentEnums {
    Apple(1,"苹果"),
    Banana(2,"香蕉"),
    Grape(3,"葡萄"),

    Computer(101,"电脑"),
    Phone(102,"手机"),
    Camera(103,"摄像机"),
    

    Fruit(10010,"fruit"),
    EleProduct(10020,"eleProduct");


    private Integer code;
    private String desc;

    ContentEnums(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

Test class:

public class GoodsTest4 {
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods(ContentEnums.Fruit.getDesc(), ContentEnums.Apple.getCode());
        Goods goods_2 = new Goods(ContentEnums.EleProduct.getDesc(), ContentEnums.Phone.getCode());
        System.out.println(goods.getName());
        System.out.println(goods_2.getName());
    }
}

Seeing this, everyone may have doubts. Compared 枚举with 常量类, are there any advantages?

  1. Enumeration is actually a special class that can carry multi-dimensional information of objects, but constant classes often can only carry fields, and the information is relatively single
  2. Enumerations can be used with switch statements instead ofif/else
ContentEnums content = ContentEnums.Apple;

switch (content) {
    case Apple:
        System.out.println("苹果");
        break;
    case Banana:
        System.out.println("香蕉");
        break;
    case Grape:
        System.out.println("葡萄");
        break;
    default:
        System.out.println("未找到匹配类型");
}
  1. enum has a very interesting feature that it is possible to write methods for enum instances
public enum MethodEnums {
    VERSION {
        @Override
        String getInfo() {
            return System.getProperty("java.version");
        }
    },
    DATE_TIME {
        @Override
        String getInfo() {
            return
                    DateFormat.getDateInstance()
                            .format(new Date());
        }
    };
    abstract String getInfo();

    public static void main(String[] args) {
        for(MethodEnums csm : values()) {
            System.out.println(csm.getInfo());
        }

    }
}

result:

1.8.0_271

2022-9-21

In addition to abstract methods, ordinary methods are also possible, which will not be shown here

  1. There are other advantages on the Internet, and I feel that there is nothing particularly worth mentioning.

type of restricted input

We can put related states and types together through enumeration, the beginning of the article, but how can we limit the input value of the class? It's actually very simple, don't get caught up, we just need to change the input type to the specified enumeration Let's
transform the Goods class:

public class Goods {
    /**
     * 商品名称
     */
    private String name;
    /**
     * 商品类型
     */
    private Integer type;

//    public Goods(String name, Integer type) {
//        this.name = name;
//        this.type = type;
//    }

    public Goods() {//防止外部实例化

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getType() {
        return type;
    }

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

    public static Goods addGoods(ContentEnums enums){
        Goods goods = new Goods();
        goods.setName(enums.getDesc());
        goods.setType(enums.getCode());
        return goods;
    }
}

Test class:

public class GoodsTest5 {
    public static void main(String[] args) throws InterruptedException {
        Goods goods = Goods.addGoods(ContentEnums.Apple);
        Goods goods_2 = Goods.addGoods(ContentEnums.Computer);
        System.out.println(goods.getName());
        System.out.println(goods_2.getName());
    }
}

In this way, we can limit the input value type when creating an object

Can enums be compared using ==?

You can use ==to compare enum instances, and the compiler will automatically provide the equals()sum  hashCode() method for you. Enum A class implements  Comparablean interface, so it has  compareTo() methods. At the same time, it also implements  Serializable the interface.

Enumeration implements singleton

Enumeration types are inherently thread-safe and will only be loaded once. We can take advantage of this feature of enumerations to implement singletons

public enum SingleInstance {
    INSTANCE;
    public void funDo() {
          System.out.println("doSomething");
    }
}

How to use: SingleInstance.INSTANCE.funDo()
This method makes full use of the characteristics of enumeration and lets JVM help us ensure thread safety and single instance issues. The writing is also extremely concise.


Reference:
《On Java 8》
《Effective java》 3rd edition

 

The author of this article: Maverick Hululu

Link to this article: https://www.cnblogs.com/xiaoniuhululu/p/16812466.html

Guess you like

Origin blog.csdn.net/weixin_47367099/article/details/127486000