有人能提供一个简单的例子来说明Java中动态和静态多态之间的区别吗?
有人能提供一个简单的例子来说明Java中动态和静态多态之间的区别吗?
编译时多态性(静态绑定/早期绑定): 在静态多态性中,如果我们在代码中调用一个方法,则该方法的哪个定义实际上将被调用是仅在编译时解决的。
(或)
在编译时,Java通过检查方法签名来确定要调用哪个方法。因此,这被称为编译时多态性或静态绑定。
动态多态性(晚期绑定/运行时多态性): 在运行时,Java等到运行时才确定引用指向的实际对象。由于方法解析是在运行时进行的,因此我们称之为运行时多态性。
public class X
{
public void methodA() // Base class method
{
System.out.println ("hello, I'm methodA of class X");
}
}
public class Y extends X
{
public void methodA() // Derived Class method
{
System.out.println ("hello, I'm methodA of class Y");
}
}
public class Z
{
public static void main (String args []) {
//this takes input from the user during runtime
System.out.println("Enter x or y");
Scanner scanner = new Scanner(System.in);
String value= scanner.nextLine();
X obj1 = null;
if(value.equals("x"))
obj1 = new X(); // Reference and object X
else if(value.equals("y"))
obj2 = new Y(); // X reference but Y object
else
System.out.println("Invalid param value");
obj1.methodA();
}
}
现在,仅从代码中你无法确定哪个methodA()的实现将被执行,因为它取决于用户在运行时给出的值。因此,在运行时才决定调用哪个方法。因此,这就是运行时多态性。
B * b = new C(); b->method1();
,则编译器将解析b指向C内部的B对象(对于简单类继承类的情况,C内部的B对象和C将从相同的内存地址开始,因此不需要执行任何操作;它将指向它们都使用的vptr)。如果C继承B和A,则C内部的A对象的虚函数表条目method1将具有一个thunk,该thunk将偏移指针到封装C对象的开头,然后将其传递给C覆盖的真正的A :: method1()文本段。对于C * c = new C(); c->method1()
,c已经指向外部C对象,并且指针将传递到文本段中的C :: method1()。参考:http://www.programmersought.com/article/2572545946/
在Java中,对于B b = new C(); b.method1();
,虚拟机能够动态检查与b配对的对象的类型,并传递正确的指针并调用正确的方法。虚拟机的额外步骤消除了虚函数表或类型在编译时被解析的需要,即使在编译时可以知道它。这只是一种不同的方式,在涉及虚拟机且代码仅编译为字节码时是有意义的。方法重载是一种编译时多态性,让我们来举个例子来理解这个概念。
class Person //person.java file
{
public static void main ( String[] args )
{
Eat e = new Eat();
e.eat(noodle); //line 6
}
void eat (Noodles n) //Noodles is a object line 8
{
}
void eat ( Pizza p) //Pizza is a object
{
}
}