在我提出问题之前,让我解释一下我的理解和意见。
- 除非有向上转换,否则仅通过覆盖我们无法实现多态性。由于它只能在运行时看到,人们可能将其命名为运行时多态。(我不反对将多态称为运行时多态)
- 我反对将方法重载称为编译时多态性或多态性。
我同意方法重载是静态绑定(编译时绑定),但我看不到多态性。
根据 javadoc,只有polymorphism。没有编译时或运行时多态性。
根据 javadoc 在名为Defining Methods的部分中,它解释了方法的重载。但是没有关于编译时多态性。
据我说:
如果将多态性归入运行时多态性类别,则在更改 JDK 版本时只能看到“编译时多态性”:
如果您从较高的 JDK 版本切换到较低的版本,您将开始看到编译错误。相同的代码在编译时表现不同,例如:lambda 表达式、菱形运算符、switch case 中的字符串、泛型等。
让我阐述一下我的观点,我对运行时多态性和编译时多态性如何出现在博客/教程中的预测:
对话1
开发人员 1:嘿,我今天读到了多态性。如果对接口进行编码,则可以实现多态性。编写代码不是与类紧密耦合,而是通过松散耦合将其写入接口,调用超类方法或接口方法实际上调用子类的方法,具体取决于传递的实例。
开发人员 2:对不起,我没听懂你。
开发人员 1:在运行时很简单,您将传递哪个对象实例,然后执行该实例方法。
开发人员 2:哦!运行时间。我知道了。
开发人员 1:是的,同一段代码,但在运行时传递的实例不同。
开发人员 2:**运行时间!好的,我明白了。
对话2
开发人员 2:嘿,昨天我遇到了开发人员 1,他正在讲述一些运行时多态性。通过覆盖子类中的方法,我们可以实现它。
开发人员 3:通过重写方法实现运行时多态性?那么什么是超载呢?编译时多态?
开发人员 2:您如何将重载称为编译时多态性?
开发人员 3:因为它只在编译时决定。
开发人员 2:安静!
接口的多态性和编码最好的例子是 java.sql:
java.sql.Connection conn = DriverManager.getConnection(DB_URL,USER,PASS);
java.sql.Statement stmt = conn.createStatement();
java.sql.ResultSet rs = stmt.executeQuery(sql);
根据注册的驱动程序,同一段代码的行为不同。这意味着,如果我们注册 Mysql 驱动程序,由于多态性,这段代码会执行 mysql 实例的方法。即它执行被覆盖的方法。如果您注册了 Oracle 驱动程序,它适用于 Oracle,依此类推。
上面我们发现相同的代码表现不同。
现在任何人都可以向我展示在编译时表现不同的相同代码。或者换句话说add(3,4)
,在编译期间向我展示绑定到不同方法(其他签名方法)的方法?
Java 编程语言支持重载方法,Java 可以区分具有不同方法签名的方法。
该方法将根据匹配的签名执行。方法名称相同并不意味着存在多态性,因为调用方法的签名不同:
问题1:如果您不更改调用方法签名,它会调用与签名匹配的方法不同的方法吗?在任何情况下,它的行为都会有所不同吗?
让我们看一下方法重载:
public void add(int a, int b)
{
System.out.println(a+b);
}
public void add(int a, int b, int c)
{
System.out.println(a+b+c);
}
public static void main(String[] args)
{
add(3,4);
add(3,4,5);
}
问题 1:如果方法重载是多态,那么在上面的代码块中哪段代码的行为不同?这里的多态性在哪里?
问题2:add(3,4);
在什么场景下显示多态的方法调用,除非它被修改为add(3,4,5)
?
编辑
@FutureVisitor,因为这个线程没有找到支持方法重载作为一种多态性的答案(即使在提出一个月的问题之后),没有任何理由接受支持方法重载的答案不是多态性,如果有任何答案点问题在我关于方法重载不是多态的论点中将被接受并支持他们的观点。