package com.test19;

class Father {

	public void publicMethod() {
		privateMethod();
		// this是Son对象,调用Father的方法
		Son son = (Son)this;
		System.out.println(son);
		this.privateMethod();
	}

	private void privateMethod() {
		System.out.println("Father.privateMethod()");
	}

	public void tm() {
		System.out.println("Father.tm()");
	}
}

class Son extends Father {

	public void publicMethod() {
		System.out.println("Son.publicMethod()");
	}

	public void tm() {
		super.tm();
		finalMethod();
	}

	public final void finalMethod() {
		System.out.println("Son.finalMethod()");
	}
}

public class TestInvokeMethod {
	public static void main(String[] args) {
		Father test = new Son();
		test.publicMethod(); // Son.publicMethod()
	}
}

  

在运行时,this对象是Son,但是通过this.privateMethod()调用的是Father类的私有方法,因为运行时,invokespecial选择方法基于引用声明的类型,而不是对象实际的类型。但invokevirtual则选择当前引用的对象的类型。

当为子类添加public void privateMethod(){}方法时,仍然调用父类方法,没有任何影响。 

以下情况使用invokespecial操作码:

1、init()函数,就是调用构造函数生产一个实例的时候。

2、私有方法

3、通过super.method()形式调用的方法

 

TestInvokeMethod.class

Constant pool:
   #1 = Methodref          #6.#15         //  java/lang/Object."<init>":()V
   #2 = Class              #16            //  com/test19/Son
   #3 = Methodref          #2.#15         //  com/test19/Son."<init>":()V
   #4 = Methodref          #17.#18        //  com/test19/Father.publicMethod:()V
   #5 = Class              #19            //  com/test19/TestInvokeMethod
   #6 = Class              #20            //  java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               SourceFile
  #14 = Utf8               TestInvokeMethod.java
  #15 = NameAndType        #7:#8          //  "<init>":()V
  #16 = Utf8               com/test19/Son
  #17 = Class              #21            //  com/test19/Father
  #18 = NameAndType        #22:#8         //  publicMethod:()V
  #19 = Utf8               com/test19/TestInvokeMethod
  #20 = Utf8               java/lang/Object
  #21 = Utf8               com/test19/Father
  #22 = Utf8               publicMethod
{
  public com.test19.TestInvokeMethod();
    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 28: 0

  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class com/test19/Son
         3: dup
         4: invokespecial #3                  // Method com/test19/Son."<init>":()V
         7: astore_1
         8: aload_1
         9: invokevirtual #4                  // Method com/test19/Father.publicMethod:()V
        12: return
      LineNumberTable:
        line 30: 0
        line 31: 8
        line 33: 12
}

  

Father.class

Constant pool:
   #1 = Methodref          #4.#14         //  java/lang/Object."<init>":()V
   #2 = Methodref          #3.#15         //  com/test19/Father.privateMethod:()V
   #3 = Class              #16            //  com/test19/Father
   #4 = Class              #17            //  java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Utf8               LineNumberTable
   #9 = Utf8               publicMethod
  #10 = Utf8               privateMethod
  #11 = Utf8               tm
  #12 = Utf8               SourceFile
  #13 = Utf8               TestInvokeMethod.java
  #14 = NameAndType        #5:#6          //  "<init>":()V
  #15 = NameAndType        #10:#6         //  privateMethod:()V
  #16 = Utf8               com/test19/Father
  #17 = Utf8               java/lang/Object
{
  com.test19.Father();
    flags:
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  public void publicMethod();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #2                  // Method privateMethod:()V
         4: aload_0
         5: invokespecial #2                  // Method privateMethod:()V
         8: return
      LineNumberTable:
        line 6: 0
        line 7: 4
        line 8: 8

  public void tm();
    flags: ACC_PUBLIC
    Code:
      stack=0, locals=1, args_size=1
         0: return
      LineNumberTable:
        line 12: 0
}

  

Son.class

Constant pool:
   #1 = Methodref          #5.#15         //  com/test19/Father."<init>":()V
   #2 = Methodref          #5.#16         //  com/test19/Father.tm:()V
   #3 = Methodref          #4.#17         //  com/test19/Son.finalMethod:()V
   #4 = Class              #18            //  com/test19/Son
   #5 = Class              #19            //  com/test19/Father
   #6 = Utf8               <init>
   #7 = Utf8               ()V
   #8 = Utf8               Code
   #9 = Utf8               LineNumberTable
  #10 = Utf8               publicMethod
  #11 = Utf8               tm
  #12 = Utf8               finalMethod
  #13 = Utf8               SourceFile
  #14 = Utf8               TestInvokeMethod.java
  #15 = NameAndType        #6:#7          //  "<init>":()V
  #16 = NameAndType        #11:#7         //  tm:()V
  #17 = NameAndType        #12:#7         //  finalMethod:()V
  #18 = Utf8               com/test19/Son
  #19 = Utf8               com/test19/Father
{
  com.test19.Son();
    flags:
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method com/test19/Father."<init>":()V
         4: return
      LineNumberTable:
        line 16: 0

  public void publicMethod();
    flags: ACC_PUBLIC
    Code:
      stack=0, locals=1, args_size=1
         0: return
      LineNumberTable:
        line 18: 0

  public void tm();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #2                  // Method com/test19/Father.tm:()V
         4: aload_0
         5: invokevirtual #3                  // Method finalMethod:()V
         8: return
      LineNumberTable:
        line 21: 0
        line 22: 4
        line 23: 8

  public final void finalMethod();
    flags: ACC_PUBLIC, ACC_FINAL
    Code:
      stack=0, locals=1, args_size=1
         0: return
      LineNumberTable:
        line 25: 0
}

final方法的调用也用invoke  

invokespecial与invokevirtual指令的区别的更多相关文章

  1. JSP中的编译指令和动作指令的区别

    JSP中的编译指令和动作指令的区别 1.编译指令是通知Servlet引擎的处理消息,而动作指令只是运行时的脚本动作 2.编译指令是在将JSP编译成Servlet时起作用,而动作指令可替换成JSP脚本, ...

  2. 『现学现忘』Docker基础 — 36、CMD指令和ENTRYPOINT指令的区别

    目录 1.CMD指令和ENTRYPOINT指令说明 2.CMD指令只有最后一条生效的原因 3.CMD指令演示 4.ENTRYPOINT指令演示 5.总结 CMD指令和ENTRYPOINT指令作用都是指 ...

  3. LEA指令与MOV指令的区别——发现一本汇编好书

    一.汇编语言中PTR的含义及作用mov ax,bx ;是把BX寄存器“里”的值赋予AX,由于二者都是word型,所以没有必要加“WORD”mov ax,word ptr [bx];是把内存地址等于“B ...

  4. 汇编中中括号[]作用以及lea和mov指令的区别

    现在总结一下:其中牵扯到lea指令,mov指令,[] 一.lea指令:对于寄存器来说:第二个操作数是寄存器必须要加[],不然报错,这里lea就是取[寄存器]的值,如:mov eax,2lea ebx, ...

  5. HC-05与HC-06的AT指令的区别

    蓝牙HC-05与HC-06对比指令集 高电平->AT命令响应工作状态     低电平->蓝牙常规工作状态 <重新上电表示完成复位> HC-05 可以主从切换模式,但是HC-06 ...

  6. AngularJS展示数据的ng-bind指令和{{}} 区别

    在AngularJS中显示模型中的数据有两种方式: 一种是使用花括号插值的方式: 1 <p>{{text}}</p> 另一种是使用基于属性的指令,叫做ng-bind: 1 &l ...

  7. 蓝牙进阶之路 (002) - HC-05与HC-06的AT指令的区别(转)

    蓝牙HC-05与HC-06对比指令集 高电平->AT命令响应工作状态     低电平->蓝牙常规工作状态 <重新上电表示完成复位> HC-05 可以主从切换模式,但是HC-06 ...

  8. include动作和include指令的区别

    1. include指令在被导入页面时,会与原有的jsp代码完全融合,共同生成同一个Servlet:而include动作则会在原有的jsp代码使用include方法而被导入页面,所以includ指令在 ...

  9. mov指令和 add以及sub 指令的区别

                比如  mov ax,ds             比如 [0],ds #经过上机实验 add,sub指令不能对段寄存器操作

随机推荐

  1. SharpMap源代码解析

    1. 简介 SharpMap是基于.net2.0的GIS系统.支持多种.NET开发语言(C# C++ 等).使用属性数据作为注记.符合OpenGIS的简单要素规范(OpenGIS Simple Fea ...

  2. (最小生成树) 畅通工程再续 -- HDU --1875

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1875 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  3. 【lazy标记得思想】HDU3635 详细学习并查集

    部分内容摘自以下大佬的博客,感谢他们! http://blog.csdn.net/dm_vincent/article/details/7769159 http://blog.csdn.net/dm_ ...

  4. C# Timer类

    C# 有三种不同的Timer类 1.Threading.Timer 2.Timer.Timer 3.Forms.Timer using System; using System.Collections ...

  5. java web 项目启动的根目录,以及项目启动后使用的端口具体是哪一个

    1.今天启动项目发现一直找不到网页,原来是自己浏览器地址的根目录出现了问题,那么系统中的根目录(也就是项目名)到底是哪个,究竟以哪个为基准? 这里有一地方不能忽视:见图片 在普通的java web项目 ...

  6. 【实战TFS】【QQ群】了解别人是如何使用TFS的

    长时间在这个QQ群里面混,了解到其他人是如何使用TFS系统的,也与网友们一起探讨,共同提高,还有分享的大量资料文档. 推荐一下:):)

  7. python 实现九型人格测试小程序

    用python实现九型人格测试,并把测试结果绘制成饼图,实现代码如下: # @Description: 九型人格 import xlrd, matplotlib.pyplot as plt data ...

  8. 纸壳CMS替换默认实现

    简介 纸壳CMS是一个开源免费的可视化内容管理建站系统,拖拽就可以轻松建网站. GitHub: http://github.com/SeriaWei/ZKEACMS 纸壳CMS在设计上使用的是ASP. ...

  9. .net core2.0 codefirst 创建数据库的问题!

    appsettings.json和Startup.cs就不记录了,网上很多!! 1.必须在有DbContext类的项目里添加这3个NuGet引用 Microsoft.EntityFrameworkCo ...

  10. AtomicBoolean

    它的两种用法: 1.保证某段语句只执行一次. 首先我们要知道compareAndSet的作用,判断对象当时内部值是否为第一个参数,如果是则更新为第二个参数,且返回ture,否则返回false.那么默认 ...