Java中,有一个名叫方法签名的东西,它的定义是这样的
Definition: Two of the components of a method declaration comprise the method signature—the method’s name and the parameter types.
大概意思是,方法签名有两部分组成——方法名和参数列表
我上面的函数的方法签名就是 hand(int a,int b) 而简单来说,JVM就是通过方法签名来决定去调用哪一个方法的,而从方法签名的组成部分来说,返回类型并不在方法签名中,所以当一个类中出现方法名参数列表相同,只有返回类型不同时,JVM无法根据方法签名来确定该调用哪一个方法,所以会报错。
参考:https://blog.csdn.net/qq_53574615/article/details/130379554
扩展:
可以通过修改字节码,把函数修改成同名:
构造两个不同名字 相同参数的成员函数:
public class OverWrite {
public String getString(String str) {
return str;
}
public void getString1(String str) {
return;
}
}
通过javap -v 命令查看字节码:
D:\Program Files\Java\jdk1.8.0_331\bin>javap.exe -v D:\project\test\out\production\test\OverWrite.class
Classfile /D:/project/test/out/production/test/OverWrite.class
Last modified 2023-8-17; size 504 bytes
MD5 checksum 40c07ae9b391609cd8fb00b3d2924ce2
Compiled from "OverWrite.java"
public class OverWrite
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#19 // java/lang/Object."<init>":()V
#2 = Class #20 // OverWrite
#3 = Class #21 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 LocalVariableTable
#9 = Utf8 this
#10 = Utf8 LOverWrite;
#11 = Utf8 getString
#12 = Utf8 (Ljava/lang/String;)Ljava/lang/String;
#13 = Utf8 str
#14 = Utf8 Ljava/lang/String;
#15 = Utf8 getString1
#16 = Utf8 (Ljava/lang/String;)V
#17 = Utf8 SourceFile
#18 = Utf8 OverWrite.java
#19 = NameAndType #4:#5 // "<init>":()V
#20 = Utf8 OverWrite
#21 = Utf8 java/lang/Object
{
public OverWrite();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LOverWrite;
public java.lang.String getString(java.lang.String);
descriptor: (Ljava/lang/String;)Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=2
0: aload_1
1: areturn
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 2 0 this LOverWrite;
0 2 1 str Ljava/lang/String;
public void getString1(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=0, locals=2, args_size=2
0: return
LineNumberTable:
line 7: 0
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 this LOverWrite;
0 1 1 str Ljava/lang/String;
}
SourceFile: "OverWrite.java"
可以看到getString 和 getString1 的两个函数定义
可以通过字节码修改工具把getString1改成getString,实际class还是可以跑的。
Main函数中记录了调用的返回值信息:
所以即使OverWrite.class中有两个同名不同返回值的函数,JVM可以进行正常跑,只不过java编译器做了如此限定。
知识来源:
【基础】重载和重写的区别_哔哩哔哩_bilibili
【2023年面试】Java中重写和重载的区别_哔哩哔哩_bilibili