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.让不注意基础的人迷糊
虽然匿名类从某个角度出发不是那么友好(例如学习和维护),但不妨碍性能和开发效率,所以还是非常好用的。
从另外一个角度出发,技巧性少一些,其实有时候更有利于学习和工程,但既然有了,既然已经学了,那么就用吧。