细究一下Java的动态绑定机制(非常重要)

简介: Java重要特性:动态绑定机制运行时绑定也叫动态绑定,它是一种调用对象方法的机制。Java调用对象方法时,一般采用运行时绑定机制。1.当调用对象方法时,该方法会和该对象的内存地址、运行类型绑定2.当调用对象属性时,没有动态绑定机制,那里声明,那里使用

Java的动态绑定机制(非常重要)


Java重要特性:动态绑定机制

运行时绑定也叫动态绑定,它是一种调用对象方法的机制。Java调用对象方法时,一般采用运行时绑定机制。

1.当调用对象方法时,该方法会和该对象的内存地址、运行类型绑定

2.当调用对象属性时,没有动态绑定机制,那里声明,那里使用

1.Java的方法调用过程

编译器查看对象的声明类型和方法名(对象变量的声明类型)。通过声明类型找到方法列表。

编译器查看调用方法时提供的参数类型。

如果方法是private、static、final或者构造器,编译器就可以确定调用那个方法。这是静态绑定。

如果不是上述情况,就要使用运行时(动态)绑定。


在程序运行时,采用动态绑定意味着:虚拟机将调用对象实际类型所限定的方法。

2.运行时(动态)绑定的过程

虚拟机提取对象的实际类型的方法表;

虚拟机搜索方法签名;

调用方法。

注意,这里说的是对象的实际类型。即在多态的情况下,虚拟机可以找到所运行对象的真正类型。

3.在向上转型情况下的动态绑定示例

public class Father { 
   public void method() { 
     System.out.println("父类方法,对象类型:" + this.getClass()); 
   } 
 } 
 public class Son extends Father { 
   public static void main(String[] args) { 
     Father sample = new Son();//向上转型 
     sample.method(); 
   } 
 } 

结果1:

父类方法,对象类型:class samples.Son

这个结果没有疑问,声明的是父类的引用(句柄),但准确的调用了子类的对象,调用method,在子类中没有该方法,所以去父类中寻找到并调用之。

现在修改子类,重写(override)method方法。

Java代码

 public class Son extends Father {  
   public void method() {  
     System.out.println("子类方法,对象类型:" + this.getClass());  
   }  
   public static void main(String[] args) {  
     Father sample = new Son();//向上转型  
     sample.method();  
   }  
 } 
 public class Son extends Father { 
   public void method() { 
     System.out.println("子类方法,对象类型:" + this.getClass()); 
   } 
   public static void main(String[] args) { 
     Father sample = new Son();//向上转型 
     sample.method(); 
   } 
 } 

结果2:

子类方法,对象类型:class samples.Son


这个结果也是意料之中的。调用method时,在子类中寻找到了该方法,所以直接调用之。


**4.静态绑定成员变量


** 在处理Java类中的成员变量时,并不是采用运行时绑定,而是一般意义上的静态绑定。所以在向上转型的情况下,对象的方法可以“找到”子类,而对象的属性还是父类的属性。

现在再进一步变化,在父类和子类中同时定义和赋值同名的成员变量name,并试图输出该变量的值。


结果3:

调用的成员:父亲属性


这个结果表明,子类的对象(由父类的引用handle)调用到的是父类的成员变量。所以必须明确,运行时(动态)绑定针对的范畴只是对象的方法。

 Java代码
 public class Father { 
   protected String name="父亲属性"; 
   public void method() { 
     System.out.println("父类方法,对象类型:" + this.getClass()); 
   } 
 } 
 public class Son extends Father { 
   protected String name="儿子属性"; 
   public void method() { 
     System.out.println("子类方法,对象类型:" + this.getClass()); 
   } 
   public static void main(String[] args) { 
     Father sample = new Son();//向上转型,new Son() 时候是先构造父类的 
     System.out.println("调用的成员:"+sample.name); 
   } 
 } 

结果3:

调用的成员:父亲属性

这个结果表明,子类的对象(由父类的引用handle)调用到的是父类的成员变量。所以必须明确,运行时(动态)绑定针对的范畴只是对象的方法。

现在试图调用子类的成员变量name,该怎么做?最简单的办法是将该成员变量封装成方法getter形式。

 Java代码 
 public class Father {  
   protected String name = "父亲属性";  
   public String getName() {  
     return name;  
   }  
   public void method() {  
     System.out.println("父类方法,对象类型:" + this.getClass());  
   }  
 }  
 public class Son extends Father {  
   protected String name="儿子属性";  
   public String getName() {  
     return name;  
   }  
   public void method() {  
     System.out.println("子类方法,对象类型:" + this.getClass());  
   }  
   public static void main(String[] args) {  
     Father sample = new Son();//向上转型  
     System.out.println("调用的成员:"+sample.getName());  
   }  
 } 

结果4:

调用的成员:儿子属性

总结:属性不能被虚拟调用,因为他不能被重写,而方法可以,它被对象的真实类型调用。

案例分析

public class extendsTest{
//main方法中
  public static void main(String[] args) {
    A a = new B(); 
    System.out.println(a.sum());
    System.out.println(a.i);
  }
}
class A{ //父类
  public int i  = 10;
  public int sum()
  {
    return i+10;
  }
}
class B extends A{//子类
  public int  i = 20;
  public int sum()
  {
    return i+20;
  }
}
//final修饰的对象(内存)不能改变,但是数组内容可以
    final int [] v = {0,0};
    System.out.println(v);
    v[1]=1;
    System.out.println(v);

动态绑定小结

  • 在程序运行时,采用动态绑定意味着:虚拟机将调用对象实际类型所限定的方法。


  • 运行时绑定也叫动态绑定,它是一种调用对象方法的机制。Java调用对象方法时,一般采用运行时绑定机制。

  • 在动态绑定的问题中必须要细心考虑所处代码环境

  • 这里用到了向上转型,换言之,就是用父类的引用变量去引用子类的实例,这是允许的。当向上转型之后,父类引用变量可以访问子类中属于父类的属性和方法,但是不能访问子类独有的属性和方法。


目录
相关文章
|
2天前
|
存储 缓存 监控
Java中的数据一致性与分布式锁机制
Java中的数据一致性与分布式锁机制
|
8天前
|
Java
并发编程的艺术:Java线程与锁机制探索
【6月更文挑战第21天】**并发编程的艺术:Java线程与锁机制探索** 在多核时代,掌握并发编程至关重要。本文探讨Java中线程创建(`Thread`或`Runnable`)、线程同步(`synchronized`关键字与`Lock`接口)及线程池(`ExecutorService`)的使用。同时,警惕并发问题,如死锁和饥饿,遵循最佳实践以确保应用的高效和健壮。
24 2
|
8天前
|
Java 数据安全/隐私保护
深入剖析:Java Socket编程原理及客户端-服务器通信机制
【6月更文挑战第21天】Java Socket编程用于构建网络通信,如在线聊天室。服务器通过`ServerSocket`监听,接收客户端`Socket`连接请求。客户端使用`Socket`连接服务器,双方通过`PrintWriter`和`BufferedReader`交换数据。案例展示了服务器如何处理每个新连接并广播消息,以及客户端如何发送和接收消息。此基础为理解更复杂的网络应用奠定了基础。
|
5天前
|
Java
Java中的`synchronized`关键字是一个用于并发控制的关键字,它提供了一种简单的加锁机制来确保多线程环境下的数据一致性。
【6月更文挑战第24天】Java的`synchronized`关键字确保多线程数据一致性,通过锁定代码块或方法防止并发冲突。同步方法整个方法体为临界区,同步代码块则锁定特定对象。示例展示了如何在`Counter`类中使用`synchronized`保证原子操作和可见性,同时指出过度使用可能影响性能。
19 4
|
3天前
|
存储 安全 Java
Java内省(Introspector)机制:深入理解与应用
Java内省(Introspector)机制:深入理解与应用
|
5天前
|
安全 Java 程序员
在Java中,finalization是一种机制,允许对象在被垃圾收集器回收之前执行一些清理操作。
【6月更文挑战第24天】Java中的finalization机制允许对象在被垃圾收集前执行清理,以释放系统资源或处理敏感信息。`finalize()`方法用于定义此类操作,但它不是可靠的资源管理策略,因为调用时机不确定且可能影响性能。尽管可用于清理外部资源或作为保护措施,但应避免依赖finalization,而应优先采用手动资源管理,遵循“创建者负责”原则。
10 1
|
11天前
|
监控 算法 Java
深入理解Java虚拟机:垃圾收集机制的奥秘
【6月更文挑战第17天】在Java的世界,垃圾收集(GC)是保持内存健康不可或缺的一环。本文将揭开JVM垃圾收集的神秘面纱,探索其原理、算法及调优策略,帮助开发者更好地理解和掌握这一关键技术,确保Java应用的性能与稳定性。
22 5
|
10天前
|
Java 开发者
Java中的异常处理机制
Java中的异常处理机制
17 2
|
10天前
|
Java 程序员
Java中实现动态性的原理和机制
Java中实现动态性的原理和机制
17 1
|
1天前
|
SQL 缓存 Java
Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件
Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件