Enum枚举

扶醉桌前 提交于 2020-01-13 04:53:52

枚举

没想到一个小小的枚举,也有这么深的知识。

为了获取枚举上一个废弃标识注解,找遍了百科,坑死我了。

还好公司有大佬,破了难题。很奇怪他是怎么知道用getField的。

--一路追踪,原来一开始想的都是内部类,怎么得到实例对象,一开始就偏了。 终于明白了。故记下本次学习历程。再次明白了关键字搜索的重要性。

1、枚举基本介绍

参考博文:--https://www.iteye.com/blog/whitesock-728934

                           https://wenku.baidu.com/view/5ddd914fb307e87100f69603.html

                             https://www.cnblogs.com/draem0507/p/4110987.html

1) Enum声明了name()方法和oridinal()方法,分别用于返回枚举值的名称和该枚举值在枚举类型中声明的顺序(从0开始)。

2)单例的实现

  序列化过程中写入流的只有name;反序列化过程中通过调用Enum.valueOf(Class<T> enumType, String name)静态方法构造枚举值,从而保证了枚举值的单例性。

3)ENUM$VALUES:是个private static final的数组。在枚举类初始化的时候,会实例化所有的枚举对象然后按顺序放在这个数组中

2、枚举的反射

参考博文:-https://blog.csdn.net/lufeng20/article/details/8835135

1)反射获取枚举上注解

先反射获取枚举实例如accountEnum所在class,然后获取枚举class上声明的该枚举field字段,然后用字段获取其上的Annotation注解,这样在调用注解的相关方法即可

(遇到问题可google英文)

  示例:boolean deprecated=AccountRankEnum .class.getField("UNOPEN").isAnnotationPresent(Deprecate.class);//==true

  注意:getField()--只能根据枚举的name()来获取对应的枚举实例对象。综合上述基本介绍,枚举的序列化写入流的只有                                            name(),所以根据code或message是无法反射到对象的。

public enum AccountRankEnum  implements Messageable{
    /** 未激活 */
    @Deprecated
    UNOPEN("W", "无"),
    /** 快速注册用户 */
    TWO("TWO", "二级"),
    /** 正常用户 */
    THREE("THREE", "三级"),
    FACESIGN("FACESIGN","面签");
    /** 枚举值 */
    private final String code;

    /** 枚举描述 */
    private final String message;

    /**
     * 构造一个<code>UserStatusEnum</code>枚举对象
     *
     * @param code
     * @param message
     */
    private AccountRankEnum(String code, String message) {
        this.code = code;
        this.message = message;
    }

..........

}

2)为什么用getField?

getField:主要用于反射获取类上属性字段。

对枚举类enum来说,枚举底层就是继承了Enum这个类 ,通过反编译.class文件我们可以发现,其实是在static静态代码块中完成了属性的初始化,枚举值其实都是static的静态成员,并加了final修饰词。所以可以用getField进行获取某个枚举值对象。.

反编译对象-字节码代码如下:javap -c -encodeing UTF-8 AccountRankEnum.class

字节码查看-参考博文:https://blog.csdn.net/kwame211/article/details/77677662/

3、枚举类的动态代理

 1) 不能进行cglib动态代理:原因如2),cglib是利用Enhancer获取代理对象的子类,然而枚举并没有办法被继承 ,因为枚举类时final修饰的,不能进行实例化和继承。(Cglib代理无法代理final修饰的)

             报错如下:java.lang.IllegalArgumentException: Cannot subclass final class com.xx.AccountRankEnum

Cglib代码如下 

 MyMethodIntercepter ,实现MethodInterceptor,

  //getTrueTarget传入是接口的实现类或具体的某个类。
AccountRankEnum accountEnum=(AccountRankEnum)new MyMethodIntercepter().getTrueTarget(AccountRankEnum.UNOPEN.getClass());
System.out.println(accountEnum);
System.out.println(accountEnum.code());

----------------------------------

public class MyMethodIntercepter implements MethodInterceptor {
    Object trueTarget;

    public Object getTrueTarget(Class trueTarget) {
        this.trueTarget = trueTarget;
        return Enhancer.create(trueTarget,this);
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("In cglib before invoke");
        Object result=proxy.invoke(obj,args);
        System.out.println("In cglib after invoke");
        return result;
    }
}

 2)若实现了接口,可以进行jdk代理:

    若没有实现接口,会报错:  java.lang.IllegalArgumentException: class com.xx.AccountRankEnumis not an interface

  jdk代理代码:( jdk代理只能代理接口)

    MyInvocationHandler 实现InvocationHandler,进行代理,代码如下:class MyInvocationHandler

   测试代码:

Messageable accountEnum=(Messageable)new MyInvocationHandler().getProxyTarget(AccountRankEnum.UNOPEN);
System.out.println(accountEnum);
System.out.println(accountEnum.code());
public class MyInvocationHandler implements InvocationHandler {
    Object trueTarget;

    public  Object getProxyTarget(Object obj){
        this.trueTarget=obj;
        return Proxy.newProxyInstance(Messageable.class.getClassLoader(),new Class[]{Messageable.class},this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before:"+method.getName());
        Object result=method.invoke(trueTarget);
        System.out.println("after:"+result);
        return result;
    }
}

 

 

 

  

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!