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.让不注意基础的人迷糊

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

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

 

posted @ 2022-03-15 23:10  正在战斗中  阅读(335)  评论(0编辑  收藏  举报