Serie Netty: tengo un Enum extensible, ¿quieres echarle un vistazo?

¡Acostúmbrate a escribir juntos! Este es el día 26 de mi participación en el "Nuevo plan diario de Nuggets · Desafío de actualización de abril", haga clic para ver los detalles del evento .

Introducción

Mucha gente ha usado la enumeración en java. La enumeración es un nuevo tipo al que se hace referencia en JAVA 1.5 para representar el rango que se puede enumerar, pero pocas personas pueden saber cómo funciona la enumeración en java, enum y ¿Qué tiene que ver una enumeración con eso? ¿Se puede extender Enum?

Echemos un vistazo juntos.

enumEnum

La clase de enumeración se introdujo en JAVA1.5, generalmente usamos la palabra clave enum para definir una clase de enumeración:

public enum StatusEnum {
    START(1,"start"),
    INPROCESS(2,"inprocess"),
    END(3,"end");

    private int code;
    private String desc;

    StatusEnum(int code, String desc){
        this.code=code;
        this.desc=desc;
    }
}
复制代码

En la clase de enumeración anterior, hemos personalizado el constructor y definido 3 objetos de enumeración.

Veamos cómo usar esta clase de enumeración:

    public static void main(String[] args) {
        StatusEnum start = START;
        System.out.println(start.name());
        System.out.println(start.ordinal());
        System.out.println(start.code);
        System.out.println(start.desc);
    }
复制代码

Es fácil entender que el código y la descripción se pueden generar, porque este es el atributo en nuestra clase de enumeración personalizada, pero ¿cuáles son el nombre y el ordinal? ¿De dónde vienen?

Aquí presentaremos la clase java.lang.Enum, que es la clase principal de todas las clases de enumeración de enumeración en JAVA. Los métodos name() y ordinal() se definen en esta clase:

public final int ordinal() {
        return ordinal;
    }

public final String name() {
        return name;
    }
复制代码

Donde ordinal representa la posición de la enumeración en la clase de enumeración, entonces es el nombre de la enumeración en la clase de enumeración. En el ejemplo anterior, los dos valores de START son 1 y START respectivamente.

Echemos un vistazo a la definición de la clase Enum:

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable
复制代码

Ingréselo como una clase abstracta, pero el compilador no le permite heredar de esta clase. Si fuerza la herencia, arrojará un error:

Classes cannot directly extend 'java.lang.Enum'
复制代码

Por lo tanto, los melones retorcidos fuertes no son dulces, todos deben recordar.

De hecho, no solo la clase Enum en sí misma no se puede heredar, sino también la clase Enum StatusEnum creada anteriormente.

¿Qué problema causa esto?

Si la enumeración está contenida en un contenedor externo, no puede extender la enumeración y, en algunos casos específicos, esta limitación puede causar algunos inconvenientes.

Afortunadamente, Netty también es consciente de este problema. A continuación, veamos cómo Netty lo resuelve.

Enumeración extensible en netty: ConstantPool

La clase que representa las constantes en netty se llama Constant y tiene dos propiedades, ID y nombre:

public interface Constant<T extends Constant<T>> extends Comparable<T> {

    int id();

    String name();
}
复制代码

El que almacena estas Constantes se llama ConstantPool. Hay un ConcurrentMap en ConstantPool para guardar la constante específica. Echemos un vistazo al valor del método de clase de fábrica de ConstantPool:

public T valueOf(String name) {
        return getOrCreate(checkNonEmpty(name, "name"));
    }
复制代码

El método valueOf pasa el nombre de la constante creada. Luego llame al método getOrCreate para crear una nueva constante:

    private T getOrCreate(String name) {
        T constant = constants.get(name);
        if (constant == null) {
            final T tempConstant = newConstant(nextId(), name);
            constant = constants.putIfAbsent(name, tempConstant);
            if (constant == null) {
                return tempConstant;
            }
        }

        return constant;
    }
复制代码

Puede ver que getOrCreate es para crear y obtener el objeto constante recién creado del mapa de constantes.

Usando ConstantPool

ConstantPool es una clase abstracta. Si necesitamos crear un nuevo grupo de clases de enumeración, podemos heredar directamente ConstantPool y luego implementar el método newConstant. Aquí hay un ejemplo concreto de uso:

public final class Foo extends AbstractConstant<Foo> {
  Foo(int id, String name) {
    super(id, name);
  }
}

public final class MyConstants {

  private static final ConstantPool<Foo> pool = new ConstantPool<Foo>() {
    @Override
    protected Foo newConstant(int id, String name) {
      return new Foo(id, name);
    }
  };

  public static Foo valueOf(String name) {
    return pool.valueOf(name);
  }

  public static final Foo A = valueOf("A");
  public static final Foo B = valueOf("B");
}

private final class YourConstants {
  public static final Foo C = MyConstants.valueOf("C");
  public static final Foo D = MyConstants.valueOf("D");
}
复制代码

En el ejemplo anterior, la clase de enumeración que creamos hereda de AbstractConstant y luego personaliza ConstantPool, que puede devolver el objeto Foo recién creado del grupo.

En tiempo real, ChannelOption, que a menudo se usa en Netty Channel, es una subclase de AbstractConstant. Veamos brevemente su implementación:

public class ChannelOption<T> extends AbstractConstant<ChannelOption<T>> {

    private static final ConstantPool<ChannelOption<Object>> pool = new ConstantPool<ChannelOption<Object>>() {
        @Override
        protected ChannelOption<Object> newConstant(int id, String name) {
            return new ChannelOption<Object>(id, name);
        }
    };
    public static <T> ChannelOption<T> valueOf(String name) {
        return (ChannelOption<T>) pool.valueOf(name);
    }
    public static <T> ChannelOption<T> valueOf(Class<?> firstNameComponent, String secondNameComponent) {
        return (ChannelOption<T>) pool.valueOf(firstNameComponent, secondNameComponent);
    }
    public static boolean exists(String name) {
        return pool.exists(name);
    }
    public static <T> ChannelOption<T> newInstance(String name) {
        return (ChannelOption<T>) pool.newInstance(name);
    }
复制代码

Como puede ver, ConstantPool se define en ChannelOption y luego se crea un nuevo objeto ChannelOption a través de los métodos valueOf y newInstance de ConstantPool.

Resumir

Si también desea extender la clase de enumeración, intente usar Constant y ConstantPool.

Ejemplos de este artículo pueden referirse a: learn-netty4

Obtenga más información en www.flydean.com/49-netty-ex…

¡La interpretación más popular, los productos secos más profundos, los tutoriales más concisos y muchos trucos que no conoces están esperando que los descubras!

Bienvenido a prestar atención a mi cuenta oficial: "Programe esas cosas", entienda la tecnología, ¡entiéndalo mejor!

Supongo que te gusta

Origin juejin.im/post/7090788611204841480
Recomendado
Clasificación