¿Cuál es la diferencia entre las constantes de enumeración e interfaz y las constantes de clase?

una simple necesidad

Durante nuestro desarrollo real del proyecto java, un día el "Líder Wang" de repente dio una tarea. El sistema de la empresa debe respaldar las necesidades de gestión de productos básicos. Por ejemplo, las frutas incluyen: manzanas, plátanos, uvas, etc. Los productos electrónicos incluyen : ordenadores, teléfonos móviles
, cámaras, etc.

Generalmente creamos nuevas categorías de productos 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;
    }
}

Entonces podemos usarlo directamente:

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

Pero hay un problema. El código comercial no está claro. A veces, los desarrolladores no saben 1、2、3lo que significa, y es muy peligroso escribir directamente números o cadenas en la capa del código comercial. Necesitamos una solución que no solo pueda convertir Juntar el estado y el tipo puede limitar el valor de entrada de la clase y mejorar la seguridad del proyecto

constante de interfaz

Podemos usar constantes de interfaz para resolver el problema anterior

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;
}

Veamos de nuevo la clase de prueba:

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());
    }
}

Esto permite que las constantes relacionadas estén en el mismo archivo de interfaz. Las constantes de interfaz son más concisas de escribir, pero para que otros sepan el significado de cada constante, es mejor escribir comentarios.
Pero tiene un problema al mismo tiempo, porque la interfaz en java admite herencia múltiple

  • Podemos profundizar en su código de clase de implementación, que obviamente no es razonable para una interfaz de clase constante.
  • También podemos seguir agregando constantes en sus subinterfaces, de modo que no se puedan controlar todas las constantes en la interfaz antepasada, lo que sin duda es muy peligroso.

Generalmente no se recomienda, pero las constantes de la interfaz no son inútiles, puede 内部接口lograr 分组el efecto

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;
    }
    
}

De esta forma, podemos agrupar las constantes relacionadas en una categoría, que es más concisa y clara.

constante de clase

Generalmente usamos 类常量el método:

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;
}

Nota: generalmente use la palabra clave final para modificar la clase para evitar que se herede, y haga que su constructor sea privado para evitar que se cree una instancia

Clase de prueba:

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());
    }
}

La forma en que podemos encontrar 类常量es realmente muy conveniente y no hay 多继承problemas con las constantes de la interfaz. Pero la información que puede tomar no es lo suficientemente dimensional y solo puede tomar información en un campo, sin embargo, cuando el proyecto es complejo, esperamos que muchas veces pueda tomar información de más dimensiones, similar a los objetos, con más atributos.

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

¡En este momento, el protagonista de nuestro artículo, la enumeración, hará su debut!

enumerar

¿Qué son las enumeraciones?

La enumeración es una clase especial. Todas las clases de enumeración son subclases de la clase Enum, al igual que la clase Object. Dado que la clase Java es de herencia única, no puede heredar otras clases o enumeraciones.
Las variables de enumeración no pueden usar otros datos, solo las constantes en la enumeración pueden usarse para la asignación. Puede mejorar la seguridad del programa .

Formato:

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

constante de enumeración

Primero definimos una clase de enumeración para definir constantes:

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;
    }
}

Clase de prueba:

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());
    }
}

Al ver esto, todos pueden tener dudas. Comparado 枚举con 常量类, ¿hay alguna ventaja?

  1. La enumeración es en realidad una clase especial que puede transportar información multidimensional de objetos, pero las clases constantes a menudo solo pueden transportar campos, y la información es relativamente única.
  2. Las enumeraciones se pueden usar con sentencias switch en lugar deif/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 tiene una característica muy interesante que es posible escribir métodos para instancias de enumeración
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());
        }

    }
}

resultado:

1.8.0_271

2022-9-21

Además de los métodos abstractos, también son posibles los métodos ordinarios, que no se mostrarán aquí.

  1. Hay otras ventajas en Internet, y siento que no hay nada que valga la pena mencionar en particular.

tipo de entrada restringida

Podemos juntar estados y tipos relacionados a través de la enumeración, al comienzo del artículo, pero ¿cómo podemos limitar el valor de entrada de la clase? En realidad, es muy simple, no se deje atrapar, solo necesitamos cambiar el tipo de entrada a la enumeración especificada. Transformemos
la clase Goods:

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;
    }
}

Clase de prueba:

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());
    }
}

De esta manera, podemos limitar el tipo de valor de entrada al crear un objeto

¿Se pueden comparar las enumeraciones usando ==?

Puede usar para comparar instancias de enumeración, y el compilador  le ==proporcionará automáticamente el método equals()de suma  .  Una clase implementa  una interfaz, por lo que tiene   métodos. Al mismo tiempo, también implementa  la interfaz.hashCode()EnumComparablecompareTo()Serializable 

La enumeración implementa singleton

Los tipos de enumeración son intrínsecamente seguros para subprocesos y solo se cargarán una vez. Podemos aprovechar esta función de enumeraciones para implementar singletons

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

Cómo se usa: SingleInstance.INSTANCE.funDo()
este método hace un uso completo de las características de la enumeración y permite que JVM nos ayude a garantizar la seguridad de los subprocesos y los problemas de instancia única. La escritura también es extremadamente concisa.


Referencia:
《En Java 8》
《Java efectivo》 3ra edición

 

El autor de este artículo: Maverick Hululu

Enlace a este artículo: https://www.cnblogs.com/xiaoniuhululu/p/16812466.html

Supongo que te gusta

Origin blog.csdn.net/weixin_47367099/article/details/127486000
Recomendado
Clasificación