• java基础匿名类/对象


    最近有同事问我,以下这个语句是什么意思?

    MqMessge<MqMessgeThink> mm= JSON.parseObject(message.toString(),new TypeReference<MqMessge<MqMessgeThink>>(){});

    就是红色粗体部分是什么意思。

    我说这是要创建一个匿名类的实例。

    一、语法和用途

    匿名类网上到处有详细的介绍,例如Java 匿名类 | 菜鸟教程 (runoob.com)

    截个图,这个图中的内容非常贴切地说明了匿名类是什么,用于什么场景。

    注意下定义匿名类的语法: new SuperClass(?){.....}

    语法分为三个部分:

    1.关键字:new

    2.父类/接口的构造方法

    3.{.....}:匿名类的实现体

    这三个组合起来就是一个意思:新建一个匿名类继承/实现某个父类/接口,并创建这个匿名类的匿名对象。

    注意,也可以为创建的对象命名,例如

    SuperClass<T> x=new SuperClass<T>(){};

    SuperClass x=new SuperClass(){};

    SuperClass<T> x=new SuperClass<T>(){

       public void do(){

          System.out.println("落后就要挨打!");

       }

    };

    如果是为了实现实现接口,那么也可以看Java 匿名类 | 菜鸟教程 (runoob.com)的例子:

    二、看具体例子

    还是以new TypeReference<MqMessge<MqMessgeThink>>(){}为例子进行说明。

    首先看下阿里TypeReference的定义:

    public class TypeReference<T> {
        static ConcurrentMap<Type, Type> classTypeCache
                = new ConcurrentHashMap<Type, Type>(16, 0.75f, 1);
    
        protected final Type type;
    
        protected TypeReference(){
            Type superClass = getClass().getGenericSuperclass();
    
            Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
    
            Type cachedType = classTypeCache.get(type);
            if (cachedType == null) {
                classTypeCache.putIfAbsent(type, type);
                cachedType = classTypeCache.get(type);
            }
    
            this.type = cachedType;
        }
    
        /**
         * @since 1.2.9
         * @param actualTypeArguments
         */
        protected TypeReference(Type... actualTypeArguments){
            Class<?> thisClass = this.getClass();
            Type superClass = thisClass.getGenericSuperclass();
    
            ParameterizedType argType = (ParameterizedType) ((ParameterizedType) superClass).getActualTypeArguments()[0];
            Type rawType = argType.getRawType();
            Type[] argTypes = argType.getActualTypeArguments();
    
            int actualIndex = 0;
            for (int i = 0; i < argTypes.length; ++i) {
                if (argTypes[i] instanceof TypeVariable &&
                        actualIndex < actualTypeArguments.length) {
                    argTypes[i] = actualTypeArguments[actualIndex++];
                }
                // fix for openjdk and android env
                if (argTypes[i] instanceof GenericArrayType) {
                    argTypes[i] = TypeUtils.checkPrimitiveArray(
                            (GenericArrayType) argTypes[i]);
                }
    
                // 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
                if(argTypes[i] instanceof ParameterizedType) {
                    argTypes[i] = handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex);
                }
            }
    
            Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
            Type cachedType = classTypeCache.get(key);
            if (cachedType == null) {
                classTypeCache.putIfAbsent(key, key);
                cachedType = classTypeCache.get(key);
            }
    
            type = cachedType;
        }
    
        public static Type intern(ParameterizedTypeImpl type) {
            Type cachedType = classTypeCache.get(type);
            if (cachedType == null) {
                classTypeCache.putIfAbsent(type, type);
                cachedType = classTypeCache.get(type);
            }
    
            return cachedType;
        }
    
        private Type handlerParameterizedType(ParameterizedType type, Type[] actualTypeArguments, int actualIndex) {
            Class<?> thisClass = this.getClass();
            Type rawType = type.getRawType();
            Type[] argTypes = type.getActualTypeArguments();
    
            for(int i = 0; i < argTypes.length; ++i) {
                if (argTypes[i] instanceof TypeVariable && actualIndex < actualTypeArguments.length) {
                    argTypes[i] = actualTypeArguments[actualIndex++];
                }
    
                // fix for openjdk and android env
                if (argTypes[i] instanceof GenericArrayType) {
                    argTypes[i] = TypeUtils.checkPrimitiveArray(
                            (GenericArrayType) argTypes[i]);
                }
    
                // 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
                if(argTypes[i] instanceof ParameterizedType) {
                    argTypes[i] = handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex);
                }
            }
    
            Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
            return key;
        }
        
        /**
         * Gets underlying {@code Type} instance.
         */
        public Type getType() {
            return type;
        }
    
        public final static Type LIST_STRING = new TypeReference<List<String>>() {}.getType();
    }

    注意,TypeReference的两个构造函数都是protected类型,这意味着在包外面是无法直接访问的。

    所以,为了能够访问,只能继承类TypeReference,怎么继承? 用匿名类(因为只用了一次)。语法如前所记述。

    三、小结

    1.创建匿名类主要是为了创建对应的实例

    2.用于继承无法直接创建的类(构造函数范围受限);实现接口

    3.简化调用方式

    4.适当减少工作量

    5.让不注意基础的人迷糊

    虽然匿名类从某个角度出发不是那么友好(例如学习和维护),但不妨碍性能和开发效率,所以还是非常好用的。

    从另外一个角度出发,技巧性少一些,其实有时候更有利于学习和工程,但既然有了,既然已经学了,那么就用吧。

  • 相关阅读:
    lua "Hello, world!"[转]
    用16进制编辑器编写一个DLL文件【转自看雪】
    Lua脚本语言入门(目前魔兽使用的可以写在宏内的语言)转自中国Lua开发者
    some tips about web hacking
    DevCpp/Mingw32/GCC专栏
    .NET中的幕后英雄MSCOREE.dll [转]
    手写可执行程序[ 转自看雪]
    VC下编译lua和luabind[转]
    简论程序是如何动态修改内存或指令的【转自看雪】
    一些链接(转仅供收藏)
  • 原文地址:https://www.cnblogs.com/lzfhope/p/16010947.html
Copyright © 2020-2023  润新知