类型推断与目标类型的关系及Map<String,Object>返回类型疑问解答
类型推断与目标类型的关系,以及代码疑问解答
一、类型推断与目标类型的关系
在Java里,类型推断是编译器根据上下文自动推导泛型、方法调用或lambda表达式具体类型的机制,而目标类型就是这个上下文所期望的类型,它是类型推断的核心依据之一,两者的关联可以从这几点拆解:
- 目标类型引导推断方向:比如我们常用的菱形运算符
<>,List<String> list = new ArrayList<>();这里ArrayList<>()的泛型类型就是根据左边的List<String>(目标类型)推断为String的——要是没有这个明确的目标类型,编译器就没法确定泛型参数。 - 方法参数作为目标类型:当你把一个方法调用的结果作为参数传给另一个方法时,被调用方法的参数类型就是目标类型。比如你的代码里
useHashMap(new HashMap<>()),new HashMap<>()的泛型类型就是根据useHashMap的参数Map<String, Object>(目标类型)推断为<String, Object>的。 - 无明确目标类型的情况:如果没有明确的目标类型(比如
var map = new HashMap<>();),编译器会根据初始化表达式自身的信息推断类型,或者退化为最具体的可行父类型。
二、代码疑问:为何var.get("key").getClass()返回Integer而非Object
先看你的代码片段:
public static void main(String[] args) { useHashMap(new HashMap<>()); } public static void useHashMap(Map<String, Object> var) { var.put("key", 1); System.out.println(var.get("key").getClass()); //prints : class java.lang.Integer }
原因其实和Java泛型的类型擦除以及getClass()方法的特性直接相关:
- 泛型是编译时语法糖:
Map<String, Object>只是编译器用来做类型检查的约束,运行时这个泛型信息会被擦除,底层的Map实际存储的都是Object类型的引用,但这些引用指向的对象的实际类型并没有改变。 - 存入的对象实际类型是Integer:当你执行
var.put("key", 1)时,1会被自动装箱为Integer实例,这个对象在运行时的类型就是Integer——编译器只是允许你把它存入Map<String, Object>(因为Integer是Object的子类),但不会改变对象本身的类型。 getClass()返回实际运行时类型:getClass()是Object类的方法,它的作用就是返回对象的实际运行时类型,而不是变量的编译时声明类型。var.get("key")的编译时类型是Object,但它指向的对象是Integer实例,所以getClass()自然返回java.lang.Integer。
简单总结:泛型约束只在编译阶段限制你能存什么类型的对象,不会改变对象本身的实际类型,getClass()看的是对象真实的运行时类型,所以结果是Integer。
内容的提问来源于stack exchange,提问作者ecdhe
相关产品推荐
相关产品推荐

