前言

说真的,平常看源码都是自己看完自己懂,很少有写出来的冲动。

但是在写算法的时候,经常用到java中各种集合,其中也比较常用到remove方法。

remove有重载函数,分别传入参数是索引index或者数据Object(指定泛型后自动转换),如果指定泛型是其他数据类型还好,但是指定的是Integer或者是int的话,或者就有点懵了。

这曾经也困惑过我,所以我就唯有用实践解惑了。

测试类设计

  • 测试类一
public class Text {

    public void remove(int index){
System.out.println("调用传参为int的remove方法");
} public void remove(Integer object){
System.out.println("调用传参为Integer的remove方法");
} public void remove(Object object){
System.out.println("调用传参为Object的remove方法");
}
}
  • 测试类二
public class Text {

    public void remove(Integer object){
System.out.println("调用传参为Integer的remove方法");
} public void remove(Object object){
System.out.println("调用传参为Object的remove方法");
}
}
  • 测试类三
public class Text {

    public void remove(Object object){
System.out.println("调用传参为Object的remove方法");
}
}

结果

三个测试类分别传入int,Integer,Object型变量,观察效果。

  • 测试类一

传入类型为int:调用传参为int的remove方法

传入类型为Integer:调用传参为Integer的remove方法

传入类型为Object:调用传参为Object的remove方法

  • 测试类二

传入类型为int:调用传参为Integer的remove方法

传入类型为Integer:调用传参为Integer的remove方法

传入类型为Object:调用传参为Object的remove方法

  • 测试类三

传入类型为int:调用传参为Object的remove方法

传入类型为Integer:调用传参为Object的remove方法

传入类型为Object:调用传参为Object的remove方法

从输出结果可以看出,当方法的传参的类层级逐渐变高时,层级较低的传参会进行向上转型适应传参的需要。

原因分析

下面我们先反编译各测试类的源码,结果如下

  • 测试类一

invokevirtual #11 // Method remove:(I)V

invokevirtual #15 // Method remove:(Ljava/lang/Integer;)V

invokevirtual #18 // Method remove:(Ljava/lang/Object;)V

  • 测试类二

invokevirtual #11 // Method remove:(Ljava/lang/Integer;)V

invokevirtual #11 // Method remove:(Ljava/lang/Integer;)V

invokevirtual #17 // Method remove:(Ljava/lang/Object;)V

  • 测试类三

invokevirtual #10 // Method remove:(Ljava/lang/Object;)V

invokevirtual #10 // Method remove:(Ljava/lang/Object;)V

invokevirtual #10 // Method remove:(Ljava/lang/Object;)V

可以看出,反编译代码中都是调用实例方法的命令,所以结果中自动"向上转型"其实是jvm的功劳。jvm通过在编译时确定调用的传参类型,静态分派到具体方法的。

所以在前言中的困惑已经解除了,就是由于jvm中静态分派的实现,调用次序是int->Integer->Object。

后记

也没什么想说的,感觉在阅读源码的时候必须多想想为什么这样做,为什么要这样实现,同时通过断点或者反编译的手段找出自己的答案。keep going!

本文首发于cartoon的博客

转载请注明出处:https://cartoonyu.github.io/cartoon-blog/post/java/java的list接口的remove重载方法调用原理/

JAVA的List接口的remove重载方法调用原理的更多相关文章

  1. java读取PHP接口数据的实现方法(四)

    PHP文件: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 3 ...

  2. 为什么Java不能以返回值区分重载方法?

    读者可能会想:"在区分重载方法的时候,为什么只能以类名和方法的形参列表作为标准呢?能否考虑用方法的返回值来区分呢?" 比如下面两个方法,虽然他们有相同的名字和形式参数,但却很容易区 ...

  3. java面试题0001-区分类中重载方法的依据是什么?

    到底是根据什么来区分类中重载的方法? A:不同的返回值类型. B:不同的参数类型. C:不同的访问权限. D:不同的参数名称. 解析: Step1.我们先在DifferentiateReload类中创 ...

  4. Java容器---Collection接口中的共有方法

    1.Collection 接口 (1)Collection的超级接口是Iterable (2)Collection常用的子对象有:Map.List.Set.Queue. 右图中实现黑框的ArrayLi ...

  5. java父类与接口有相同的方法

    这是java多态的一个体现,如果一个类classA继承了类classB,有实现了接口interfaceA,并且接口中有方法funA(),且父类classB中也有funA(),那么对于classA来说既 ...

  6. java 请求第三方接口 GET\POST 实现方法

    (1)GET方法 /** * 根据高德地图api获取位置信息 * @return * */ public static String getMapAddInfo(String httpurl) { H ...

  7. 【Java面试题】14 super.getClass()方法调用

    下面程序的输出结果是多少? import java.util.Date; public class Test extends Date{ public static void main(String[ ...

  8. JAVA中,不同工程间的方法调用

    可以调用, 用配置构建路径的方法:点选工程1, 点击右键, 选择 Build Path(构建路径) - > Configure Build Path...(配置构建路径...)然后在弹出的窗口中 ...

  9. 趣谈iOS运行时的方法调用原理

    一个成熟的计算机语言必然有丰富的体系,复杂的容错机制,处理逻辑以及判断逻辑.但这些复杂的逻辑都是围绕一个主线丰富和展开的,所以在学习计算机语言的时候,先掌握核心,然后了解其原理,明白程序语言设计的实质 ...

随机推荐

  1. gym/102021/J GCPC18 模拟拼图

    模拟拼图 题意: 给定n块拼图,每个拼图为四方形,对应四条边有四个数字,如果为0,表示这个边是在边界的,其他数字表示和另一个拼图的一条边相接.保证每个非零数只出现两次. 思路: 模拟,但是要注意几个情 ...

  2. 编码神器Lombok,学会后开发效率至少提高一倍!

    Lombok会利用注解自动生成javaBean中的getter.setter.equals.toString等一系列方法,大大提供开发效率,本文详细介绍下Lombok的安装及使用. 本文目录 一.Lo ...

  3. 良许 | 听说,有个同事因为关闭服务器被打进 ICU ……

    提问:你是如何关闭电脑的? 普通青年 文艺青年 二逼青年 你是属于哪一种呢? 实话说, 这三种良许都干过~ 还好我没有对服务器这么做, 否则-- 分分钟被打进 ICU -- 1. 关机命令知多少 对于 ...

  4. 如何在GitHub上上传自己的项目

    此文为转载,地址:https://blog.csdn.net/m0_37725003/article/details/80904824 本文链接:https://blog.csdn.net/m0_37 ...

  5. Python数据库小程序

    源代码: # dict1 是 字典 , 用来对应相应元素的下标,我们将文件转成列表,对应的也就是文件的下标,通过下标来找文件元素 dict1 = {'sort':0 , 'name':1 ,'age' ...

  6. 原生JavaScript时间倒计时的方法

    这个思路是来源用%的方法来做的: 以前用%做过转秒的 现在用来做倒计时方法: 需要用到的方法是getTime:获取距离1970年1月1日午夜00:00之间的毫秒差: var targetTime=ne ...

  7. 基于python的selenium两种文件上传操作

    方法一.input标签上传     如果是input标签,可以直接输入路径,那么可以直接调用send_keys输入路径,这里不做过多赘述,前文有相关操作方法. 方法二.非input标签上传 这种上传方 ...

  8. C#中 CS1752无法嵌入互操作类型"OPCServerClass"。请改用适用的接口。

    使用C#+VS开发OPC程序是,调用Interop.OPCAutomation中的类时,提示无法嵌入互操作类型"OPCServerClass".请改用适用的接口. 首先说一下它的含 ...

  9. Servlet控制台输出乱码问题

    在如下图的配置页面: 在此行添加编码格式:

  10. SpringCloud学习笔记(7):使用Spring Cloud Config配置中心

    简介 Spring Cloud Config为分布式系统中的外部化配置提供了服务器端和客户端支持,服务器端统一管理所有配置文件,客户端在启动时从服务端获取配置信息.服务器端有多种配置方式,如将配置文件 ...