前言

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

但是在写算法的时候,经常用到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重载方法调用原理/

最新文章

  1. Git使用方法
  2. [LeetCode] Fraction to Recurring Decimal 哈希表
  3. SQL 注入防御方法总结
  4. Could not find artifact com.sun:tools:jar:1.5.0
  5. C# 多任务之 Task
  6. Apache的httpd命令详解
  7. [算法题] Reverse Linked List II
  8. Windows搭建golang开发平台
  9. ●POJ 2079 Triangle
  10. 苹果公司揭秘首批列入 Swift 源代码兼容性开源项目清单
  11. JAVA流读取文件并保存数据
  12. 自己写的一些公共js方法
  13. Unity shader学习之渐变纹理
  14. 使用RxSwift 实现登录页面的条件绑定
  15. 浅谈如何正确给table加边框
  16. day02编程语言介绍及python介绍
  17. 对工程测量大师App的评价
  18. RPi Desktop盒子安装与服务配置
  19. golang array, slice, string笔记
  20. java多线程 -- CountDownLatch 闭锁

热门文章

  1. tabBar的内部控件
  2. Java内部类的使用小结 形参为什么要用final
  3. Java的8种基本数据类型的内存占用字节数和取值范围
  4. MyBatis基础之几道常见面试题详解
  5. Android Q 正式命名为 Android 10
  6. Nginx安装及详解
  7. 为git创建远程仓库
  8. SqlServer2014怎样还原数据库
  9. OPC—— KepServer.ServerState返回值为3和OPCConfig.exe配置文件的根目录
  10. 字符串转化成int