范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Java及JVM是如何识别重载重写方法的?

  可变长参数方法的重载造成的。(官方文档建议避免重载可变长参数方法,见[1]的最后一段。) 案例void invoke(Object obj, Object... args) { ... } void invoke(String s, Object obj, Object... args) { ... }  invoke(null, 1);    // 调用第二个invoke方法 invoke(null, 1, 2); // 调用第二个invoke方法 invoke(null, new Object[]{1}); // 只有手动绕开可变长参数的语法糖,                                // 才能调用第一个invoke方法
  某API定义了两个同名重载方法: 第一个接收一个Object,以及声明为Object…的变长参数 第二个则接收一个String、一个Object,以及声明为Object…的变长参数
  想调用第一个方法,传参(null, 1),即声明为Object的形式参数所对应的实际参数为null,而变长参数则对应1。 之所以不提倡可变长参数方法重载,是因为Java编译器可能无法决定应该调用哪个目标方法。 这种情况下,编译器会报错,并且提示这方法调用有二义性。然而,Java编译器直接将我的方法调用识别为调用第二个方法,这究竟是为什么呢?
  Java虚拟机是怎么识别目标方法的? 重载与重写
  同一类中出现多个: 名字相同 参数类型相同
  的方法,则无法编译。如想在同一个类中定义名字相同方法,它们参数类型必须不同。这些方法之间的关系称为重载。
  这限制可通过字节码工具绕开,编译完成后,可再向class文件中添加方法名和参数类型相同,而返回类型不同的方法。当这种包括多个方法名相同、参数类型相同,而返回类型不同的方法的类,出现在Java编译器的用户类路径上时,它是怎么确定需要调用哪个方法的呢? 当前版本的Java编译器会直接选取第一个方法名以及参数类型匹配的方法。并且,它会根据所选取方法的返回类型来决定可不可以通过编译,以及需不需要进行值转换等。 重载的方法在编译过程中即可完成识别。具体到每一个方法调用,Java编译器会根据所传入参数的声明类型(注意与实际类型区分)来选取重载方法。选取的过程共分为三个阶段: 在不考虑对基本类型自动装拆箱及可变长参数情况下选取重载方法 如在第1个阶段没找到适配方法,那在允许自动装拆箱,但不允许可变长参数情况下选取重载方法 如在第2个阶段中没找到适配方法,那在允许自动装拆箱及可变长参数情况下选取重载方法
  如Java编译器在同一阶段中找到多个适配方法,那它会在其中选择一个最为贴切,贴切程度关键就是形式参数类型的继承关系。
  传入null时,它既可匹配第一个方法中声明为Object的形式参数,也可匹配第二个方法中声明为String的形式参数。由于String是Object的子类,因此Java编译器会认为第二个方法更贴切。 除同一个类中的方法,重载也可作用于这个类所继承而来的方法。如子类定义了与父类中非私有方法同名的方法,且这两个方法的参数类型不同,那在子类中,这两个方法同样构成重载。
  若子类定义与父类中非private方法的同名方法,且这两方法参数类型相同,那这俩方法间啥关系: 若这俩都是static方法,那子类中的方法隐藏了父类中的方法 若都不是 static 的,则子类的方法重写了父类中的方法
  Java的方法重写是多态的体现:允许子类在继承父类部分功能同时,拥有自己独特行为。 重写调用会根据调用者的动态类型选取实际的目标方法。 JVM的静态绑定和动态绑定
  Java虚拟机识别方法的关键在于类名、方法名及方法描述符(method descriptor)。 方法描述符由方法的参数类型及返回类型构成。 同一类中,如同时出现多个名字相同且描述符相同的方法,那Java虚拟机会在类的验证阶段报错。 Java虚拟机与Java语言不同,它不限制名字与参数类型相同,但返回类型不同的方法出现在同一类,对调用这些方法的字节码,由于字节码所附带的方法描述符包含了返回类型,因此Java虚拟机能够准确识别目标方法。
  JVM方法重写判定同样基于方法描述符。 如子类定义了与父类中非私有、非静态方法同名的方法,则仅当这俩方法的参数类型及返回类型一致,JVM才会判定为重写。
  对Java中重写而Java虚拟机中非重写的情况,编译器会通过生成桥接方法[2]实现Java的重写语义。
  由于对重载方法的区分在编译阶段已完成,可认为JVM不存在重载概念。因此,某些文章将 重载称为静态绑定(static binding)或编译时多态(compile-time polymorphism) 重写称为动态绑定(dynamic binding)
  这说法在JVM语境下并非完全正确,因为某类中的重载方法可能被它的子类重写,因此JVM 会将所有对非私有实例方法的调用编译为需要动态绑定的类型。 JVM的: 静态绑定指在解析时便能够直接识别目标方法 动态绑定指要在运行过程中,根据调用者的动态类型来识别目标方法
  Java字节码中与调用相关的指令有: invokestatic:调用静态方法 invokespecial:调用私有实例方法、构造器及使用super关键字调用父类的实例方法或构造器,和所实现接口的默认方法 invokevirtual:用于调用非私有实例方法 invokeinterface:用于调用接口方法 invokedynamic:用于调用动态方法 较为复杂
  编译生成这四种调用指令的情况。 interface 客户 {   boolean isVIP(); }  class 商户 {   public double 折后价格(double 原价, 客户 某客户) {     return 原价 * 0.8d;   } }  class 奸商 extends 商户 {   @Override   public double 折后价格(double 原价, 客户 某客户) {     if (某客户.isVIP()) {                         // invokeinterface             return 原价 * 价格歧视();                    // invokestatic     } else {       return super.折后价格(原价, 某客户);          // invokespecial     }   }   public static double 价格歧视() {     // 咱们的杀熟算法太粗暴了,应该将客户城市作为随机数生成器的种子。     return new Random()                          // invokespecial            .nextDouble()                         // invokevirtual            + 0.8d;   } }
  "商户"类定义了一个成员方法,叫"折后价格",它接收一个double类型参数及一个"客户"类型参数。 这里"客户"是个接口,定义了一个接口方法"isVIP"。
  "奸商"类这个方法,首先调用客户#isVIP,该调用会被编译为invokeinterface指令 若客户是VIP,则调用奸商类的一个名叫"价格歧视"的静态方法。该调用会被编译为invokestatic指令 如客户不是VIP,则通过super调用父类的"折后价格"方法。该调用会被编译为invokespecial指令
  在静态方法"价格歧视"会调用Random类的构造器。该调用会被编译为invokespecial指令。然后以这个新建Random对象为调用者,调用Random类中的nextDouble方法。该调用会被编译为invokevirutal指令。
  对于invokestatic以及invokespecial而言,Java虚拟机能够直接识别具体的目标方法。
  而对于invokevirtual以及invokeinterface而言,在绝大部分情况下,虚拟机需要在执行过程中,根据调用者的动态类型,来确定具体的目标方法。
  如虚拟机能确定目标方法有且仅有一个,比如说目标方法被标记为final3,它可不通过动态类型,直接确定目标方法。 调用指令的符号引用
  编译过程中,我们并不知目标方法的具体内存地址。因此,Java编译器会暂时用符号引表示该目标方法。 这符号引用包括目标方法所在的类或接口的名字,以及目标方法的方法名和方法描述符。
  符号引用存储在class文件的常量池。根据目标方法是否为接口方法,这些引用可分为: 接口符号引用 非接口符号引用 // 在奸商.class的常量池中,#16为接口符号引用,指向接口方法"客户.isVIP()"。#22为非接口符号引用,指向静态方法"奸商.价格歧视()"。 $ javap -v 奸商.class ... Constant pool: ...   #16 = InterfaceMethodref #27.#29        // 客户.isVIP:()Z ...   #22 = Methodref          #1.#33         // 奸商.价格歧视:()D ...
  执行使用了符号引用的字节码前,JVM需解析这些【符号引用】并替换为【实际引用】。
  对【非接口符号引用】,假定该【符号引用】所指向的类为C,则JVM按如下步骤查找: 在C中查找符合名字及描述符的方法 若没找到,搜索C的父类,直至Object类 若还没找到,在C所直接实现或间接实现的接口中搜索,该步搜索得到的目标方法必须是非private、非static且若目标方法在间接实现的接口中,则需满足C与该接口间无其他符合条件的目标方法。若有多个符合条件的目标方法,则返回其中任一。
  所以static方法也可通过子类来调用。子类的static方法会隐藏(这不是重写)父类中的同名、同描述符的静态方法。
  对于接口符号引用,假定该符号引用所指向的接口为I,则Java虚拟机会按照如下步骤进行查找。 在I中查找符合名字及描述符的方法。 如果没有找到,在Object类中的公有实例方法中搜索。 如果没有找到,则在I的超接口中搜索。这一步的搜索结果的要求与非接口符号引用步骤3的要求一致。
  经过上述解析步骤后,符号引用会被解析成实际引用: 对可静态绑定的方法调用,实际引用是个指向方法的指针 对需动态绑定的方法调用,实际引用则是个方法表的索引 总结与实践
  本文介绍了Java以及Java虚拟机是如何识别目标方法的。
  在Java方法的: 重载,方法名相同而参数类型不相同的方法间 重写,方法名相同&参数类型也相同的方法间
  JVM识别方法的方式除了方法名和参数类型,还有返回类型。
  JVM的: 静态绑定:在解析时便能够直接识别目标方法的情况 动态绑定,需在运行过程中根据调用者的动态类型来识别目标方法的情况。由于Java编译器已区分重载方法,因此可认为JVM不存在重载
  在class文件中,Java编译器会用符号引用指代目标方法。在执行调用指令前,它所附带的符号引用需要被解析成实际引用。对于可以静态绑定的方法调用而言,实际引用为目标方法的指针。对于需要动态绑定的方法调用而言,实际引用为辅助动态绑定的信息。
  Java的重写与Java虚拟机中的重写并不一致,但编译器会通过生成桥接方法来弥补。
  [1] https://docs.oracle.com/javase/8/docs/technotes/guides/language/varargs.html [2] https://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html
  [3] https://wiki.openjdk.java.net/display/HotSpot/VirtualCalls
  [4] https://wiki.openjdk.java.net/display/HotSpot/InterfaceCalls

国家给华为的补助,华为用来搞研发的有多少?余下的干什么了?你这种问题明显带黑华为的性质。我单位333人,2020收到财政补助近3000万,都是有方向和任务的,之后还要做审计。政府给的钱不是你想怎么花就怎么花的。首先你的问题就满满的恶意,在号称18个月不卡的华为Mate9,五年过去了还能用吗?真不想用了,第一批入手的用户表示,今年春节觉得屏幕滑动有点卡滞,索性就把原厂膜撕掉,谁曾想居然跟TM新机一样顺滑,55555想换真新机啊!我是2017年买的,到现在也还在用,就是稍家用车不能只在乎油耗,这两款车实用且舒适随着生活水平的不断提高以及国家对于环境保护的重视,人们对于家用汽车的要求也变得严苛,因此,新能源家用型SUV作为千万家庭买车的首要选择,势必会精益求精。家用新能源汽车众多品牌谁更好谁在背后操控比特币?如果你是比特币的持有者,那么过去的一年,在疫情之外,你一定收获了比别人多一倍的心跳体验。去年这个时候,一枚比特币价值还不到1万美元,此后的一年,它连续攀升7个月,价值翻了两番,从1看了理想ONE,感叹插电式混动比增程式真的更靠谱时隔一年多的时间,理想汽车正式发布2021款理想ONE。而此次的改款,带来的是此起彼伏的争议声。一方面来自新车相比原来价格上涨了1万元,按照目前许多汽车厂商加量不加价原则,理想这样小白学编程matlab一读取视频文件aviread这个函数读取一个AVI电影并将其帧存入MATLAB的一个movie结构中。(新版本将用VideoReader替换aviread)movaviread(f美团回应商家能否直接降费用骑手工资占成本大头,每单利润不到3毛日前,美团在官方公众号发布消息称,从今年5月开始,推行了费率透明化试点,改变了原来粗放的收费方式,目前费率透明化改革还在试点阶段。此前,美团在部分城市更改外卖商家佣金计费规则引起热我家宽带马上到期了,请问选择哪家好?谢邀!据我所知,这三家是爹,儿子和孙子的关系。至少也是爹和俩儿子的关系。一下从稳定性,dns解析,价格加以说明。解释一下稳定性是指速度快慢,使用高峰期链接稳定,看视频卡不卡的问题。两小时损失38亿,巴菲特给苹果泼冷水,称做软件风险不小文AI财经社实习生刘一诺编鹿鸣本文由AI财经社原创出品,未经许可,任何渠道平台请勿转载。违者必究。苹果公司发布的新动向,不仅让华为公开发文称感谢暖场,也让近几年不断增持其股份,对该Reno标准版证件照现身工信部网站IT之家3月29日消息今天工信部已经曝光了OPPOReno新机的配置参数,现在其证件照也出现在了网站上,可以看到曝光的是粉色版本,双摄一小一大,与闪光灯一起居中排列。工信部公布的参热点网约车第一股即将诞生,身后的车企赚翻了每经记者黄辛旭今夜注定无眠。不管是对Uber来说,还是对即将登陆纳斯达克的Lyft来说,都是如此。作为网约车市场的一对劲敌,Lyft抢先一步IPO,这让Uber心里多少有点不爽。与
方向又错了?华为折叠屏手机遭吐槽,酷派则表明不做伪高端相信大家都有体会,智能手机的发展如今已经进入到一个艰难的瓶颈期,比如前两年手机厂商们就陷入了在相机上堆料的怪圈。而现在,大厂们又无一例外地将目标转向一个更奇特的方向整改手机屏幕。早高端WiFi6,让网速起飞的夜鹰,网件RAX50路由器上手体验家中的WiFi速度慢怎么办,除了可以升级宽带,还可以从路由器上下功夫,握手边的网件RAX50就是很好的选择。网件RAX50在官网上还有一个称呼叫夜鹰,我觉得一个是符合它酷炫的造型,1699元,摩托罗拉G71图赏与简评千元级的超长续航选择前些天,摩托罗拉首发了高通最新一代的骁龙8处理器,带来了motoedgeX30和S30两款旗舰新品,性价比可以说是拉满的。而除了旗舰之外,摩托罗拉其实也在入门级产品上提供了很多不错跨境早知道2021全球最受欢迎十大购物网站亚马逊淘宝上榜PART1今日头条01hr2021全球最受欢迎10大购物网站亚马逊第一,淘宝第二12月27日消息,近日,追踪互联网流量的云基础设施公司Cloudflare根据网站访问量,统计了20如果没有西方的工业革命,中国会还处于以冷兵器为主导的时代吗?我是萨沙,我来回答。萨沙第9430条回答。当然是不会了。其实古代除了美洲澳洲和非洲南部以外,其他亚洲欧洲和非洲北部,互相都是保持各种交流的。也就是说,世界其实是技术共享的时代,一荣干衣机什么品牌好?如今随着消费升级的不断推进,家电市场中,干衣机品类正在成为许多厂商的重要发力点,解决了用户想象不到的一些生活痛点。例如迅速烘干衣物,除菌,同时可以有效去除衣物中的油烟异味,适合快节很多车主购买新能源汽车后悔了,来看一下原因咱们先以续航为例,虽然现在新能源车续航在200到500公里左右的续航,但是这个续航指的是理想状态下的,由于车子在道路上行驶会因为不同的路况天气因素等影响,车辆的续航会出现衰减,尤其从里程焦虑到补能焦虑充电补能体系如何喂饱新能源车龚梦泽新能源汽车全年销量有望突破340万辆的喜报言犹在耳,关于电动汽车里程和补能焦虑的问题,已从熙熙攘攘的国庆高速路上蔓延到了寒潮侵袭的北方地区。低温之下,三元电池和磷酸铁锂电池内印度当局要求富士康必须改善被关闭工厂工人的生活条件一组食物中毒事件和一场抗议活动使印度的一家苹果iPhone组装工厂被迫关闭,由于工人生活条件不符合政府监管要求,重新开工的时间再次被推迟。受工人食物中毒影响的工厂关闭一周的时间将延PW热点李彦宏称5年内一线城市不再限行,10年之内基本解决拥堵问题今天是2021年12月29日,离全年的结束还有2天。1967年12月29日,黑洞一词被约翰阿奇巴德惠勒首次使用。李彦宏称5年内一线城市不再限行,10年之内基本解决拥堵问题在百度Cr8点1氪丨李彦宏称5年内一线城市不再限购限行星巴克被强制执行1087万快手与美团达成互联互通上市进行时宏裕包材36氪获悉,安琪酵母公告称,决定终止所属子公司宏裕包材分拆至深圳证券交易所创业板上市,并撤回相关上市申请文件。大公司李彦宏谈智能交通5年内中国一线城市不再限购限行