class Animal {
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move();//output: Animals can move
b.move();//output:Dogs can walk and run
}
}
public class DynamicBindingTest {
public static void main(String args[]) {
Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car
vehicle.start(); //Car's start called because start() is overridden method
}
}
class Vehicle {
public void start() {
System.out.println("Inside start method of Vehicle");
}
}
class Car extends Vehicle {
@Override
public void start() {
System.out.println("Inside start method of Car");
}
}
产出:
轿车内起动方式
静态绑定/编译时多态性:
调用哪个方法仅在编译时决定。
public class StaticBindingTest {
public static void main(String args[]) {
Collection c = new HashSet();
StaticBindingTest et = new StaticBindingTest();
et.sort(c);
}
//overloaded method takes Collection argument
public Collection sort(Collection c){
System.out.println("Inside Collection sort method");
return c;
}
//another overloaded method which takes HashSet argument which is sub class
public Collection sort(HashSet hs){
System.out.println("Inside HashSet sort method");
return hs;
}
}
class Mammal {
public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}
class Human extends Mammal {
@Override
public void speak() { System.out.println("Hello"); }
public void speak(String language) {
if (language.equals("Hindi")) System.out.println("Namaste");
else System.out.println("Hello");
}
}
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
{
}
}
例如,对于上图中的“ a1.method ()”方法调用,编译器检查类 A 中是否存在方法()的方法定义,因为‘ a1’是类 A 类型。类似地,对于“ a2.method ()”方法调用,它检查类 A 中是否存在方法()的方法定义,因为‘ a2’也是类 A 类型。它不检查指向哪个对象,‘ a1’和‘ a2’。这种类型的绑定称为静态绑定。
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();
}
}
在 C + + 中,如果要使用 gcc 将其编译成本地二进制文件,那么必须在编译时解析它; 然而,虚拟表中的运行时跳转和 thunk 仍然被称为“查找”或“动态”。如果 C 继承了 B,并且你声明了 B* b = new C(); b->method1();,那么编译器就会将 b 解析为指向 C 内部的一个 B 对象(对于一个简单的类来说,C 和 C 内部的 B 对象将从相同的内存地址开始,因此不需要做任何事情; 它将指向它们都使用的 vptr)。如果 C 继承了 B 和 A,那么 method1的 C 条目中的 A 对象的虚函数表将会有一个 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 配对的对象的类型,并能够传递正确的指针和调用正确的方法。虚拟机的额外步骤消除了对虚函数表或在编译时解析的类型的需要,即使在编译时可以知道它。这只是一种不同的方法,当涉及到虚拟机并且代码只被编译成字节码时,这种方法是有意义的。