`
smiky
  • 浏览: 257794 次
  • 性别: Icon_minigender_1
  • 来自: 天门
社区版块
存档分类
最新评论

JAVA方法分派笔记

阅读更多

有两个让我不太明白的调用:

1.http://smiky.iteye.com/admin/blogs/996590

2. 

 

package org.gerry;

public class Son extends Parent
{
	public void test()
	{
		super.test();
		System.out.println( this );
		this.duo();
	}
	public void duo()
	{
		System.out.println("Son duo");
	}
}

 

 

package org.gerry;

public class Parent
{
	public void test()
	{
		System.out.println("Parent test...");
		System.out.println( this );
		this.duo();
	}
	
	public void duo()
	{
		System.out.println("Parent duo");
	}
	
}

 

 

 

package org.gerry;

public class client
{
	public static void main(String[] args)
	{
		new Son().test();
	}
}
 

 

 

第二个的结果相信会有人跟我一样弄错,父类的test()方法内会调用那个方法?子类or父类的?

字节码先上:
parent的test方法
 public void test();
   flags: ACC_PUBLIC
   Code:
     stack=2, locals=1, args_size=1
        0: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
        3: ldc           #21                 // String Parent test...
        5: invokevirtual #23                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        8: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
       11: aload_0
       12: invokevirtual #29                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       15: aload_0
       16: invokevirtual #32                 // Method duo:()V
       19: return
     LineNumberTable:
       line 7: 0
       line 8: 8
       line 9: 15
       line 10: 19
     LocalVariableTable:
       Start  Length  Slot  Name   Signature
              0      20     0  this   Lorg/gerry/Parent;
 可以看出偏移量为16的指令为invokevirtual,说明这个方法是个多态调用,但是看下面的变量表,很显示这个this是Parent类型的,根据方法解析规则:(下面是常量表中的类方法表
#32 = Methodref          #1.#33         //  org/gerry/Parent.duo:()V)
方法的符号引用在指令调用之前替换成直接引用,先找到#1对应的Parent(不用说Parent早就换成了Parent.class对应的直接引用),即然有了Class对象,接着就是在该类中查找#33对应的NameAndType类型常量池的索引,说白了就是在类中找duo方法,找得到的话就换成方法的直接引用
照上面的分析,结果应该是调用父类的duo()才对,可为什么调用的是子类的duo呢?可能有人说,invokevirtual表示调用多态方法啊,但是我父类中有duo方法啊,就算多态也应该找我自己的啊,轮不到子类啊
出现这种情况,只能在这种情况才可能,就是Parent的本地变量表中的this的直接引用就是指向 main方法中new的那个Son,在这种情况下多态才能体现出来(只有 invokevirtual对应的操作数this是Son,它才会动态分派到Son的duo方法)

从下面的打印结果能看出这点:Son中的this与Parent中的this指向的是同一个地址
Parent test...
org.gerry.Son@2f995c9a
Son duo
org.gerry.Son@2f995c9a
Son duo
 
还有一点顺带提一下,不知道对不对,
super根本就屁用没有,只不过指定编译器执行父类的方法,下面是Son的test()的字节码:
public void test();
  flags: ACC_PUBLIC
  Code:
    stack=2, locals=1, args_size=1
       0: aload_0
       1: invokespecial #15                 // Method org/gerry/Parent.test:()V
       4: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
       7: aload_0
       8: invokevirtual #23                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      11: aload_0
      12: invokevirtual #29                 // Method duo:()V
      15: return
    LineNumberTable:
      line 7: 0
      line 8: 4
      line 9: 11
      line 10: 15
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
             0      16     0  this   Lorg/gerry/Son;
 从偏移为1的指令看出,它就是调用父类的test方法,而方法在执行的时候会传一个隐藏的this作为参数(从实际方法的本地方法表中可以看出),是不是这里是将Son的对象传到了Parent的test方法作为隐藏的this?估计也只有这个可能,
那么有什么方式可以获取到父类的对象呢?子类初始化时会初始化父类,那么生成的父类对象去那啦?可以调用到吗?如果调用不到的话在这种情况下算生成了几个对象?


对于上面第一个是不是也可以这样理解,对于属性只管其静态类型(本地变量表中的类型)?父类中的this的类型是父类本身,所以改奕的是父类的值,对子类无影响?
看来我是JS写多了,以为this是谁改变的就是谁的字段的值,走火入魔了

看来我的猜测是对的,将父类中的this强制改成子类,那么父类方法中操作的就是子类的属性了,看来对属性的操作只看静态类型
class A extends E{  
    int x;  
    int y;  
    public void setValue(int i,int j){  
        this.x = i;  
        this.y = j;  
//        B b = (B)this;
//        b.x = i;  
//        b.y = j;  
    }  
    
    public int compute(){  
        return this.x * this.y;  
    }  
      
}  
 


分享到:
评论

相关推荐

    java课程笔记

    线程可以共享系统分派给这个进程的内存空间。 2、 定义线程的方法 定义线程的方法有两种:继承 Thread 类和实现 Runnable 接口。两种方法的本质上是一种方法,即都是通过 Thread 类建立线程,并运行 run() 方法。 ...

    java并发编程笔记

    ### Java并发编程笔记 #### 一、线程与进程 - **进程**: 是操作系统资源分配的基本单位,每个进程都有自己的独立内存空间。例如,当我们打开QQ或者音乐播放器时,实际上是在启动`qq.exe`或`Music.exe`这样的程序,...

    深入理解Java虚拟机笔记(带目录).docx

    深入理解 Java 虚拟机笔记 Java 虚拟机(JVM)是 Java 语言的运行环境,它负责解释和执行 Java 字节码。下面是 Java 虚拟机相关的知识点: 虚拟机内存结构 Java 虚拟机的内存结构主要包括以下几个部分: * 方法...

    spring笔记.zip

    Spring框架是Java开发中的核心组件,它为应用程序提供...这些笔记将涵盖这些主题的基本概念、使用方法和示例,帮助初学者快速理解和掌握Spring生态系统。通过深入学习和实践,开发者能够构建出高效、可扩展的Java应用。

    servlet基础笔记

    在处理请求时,Servlet容器会调用service()方法,根据请求类型分派到doGet()或doPost()等方法。最后,当Servlet不再需要时,服务器会调用destroy()方法,释放资源。 三、Servlet部署 Servlet通常通过在Web应用的web...

    JSP&Serlet;学习笔记2

    4. **服务阶段**: 用户请求到达,调用service()方法,根据HTTP方法分派到doGet()或doPost()。 5. **销毁阶段**: 当服务器关闭或Servlet不再需要时,调用destroy()方法进行清理。 **五、Servlet生命周期** 1. **加载...

    动力节点老杜servlet学习笔记.zip

    3. 服务:每次有请求到达,Servlet容器都会调用`service()`方法,该方法会根据请求类型分派到`doGet()`或`doPost()`等具体处理方法。 4. 销毁:当Servlet不再使用或Web应用停止时,会调用`destroy()`方法释放资源。 ...

    head_first_servlet&jsp学习笔记

    3. **重定向与请求分派**:重定向改变浏览器地址,分派则在服务器内部转发请求。 【Web应用属性与监听器】 1. **属性与参数**:属性是动态存储在特定范围(请求、会话、上下文)的数据,参数通常是配置项。 2. **...

    Head First Servlets & JSP 学习笔记

    - **请求分派(Forward)**:通过`RequestDispatcher`的`forward()`方法,服务器内部转发请求,用户在浏览器中看不到URL变化。 6. **HTTP请求和响应对象**: - **HttpServletRequest**:提供请求信息,如参数、头...

    servlet中文笔记

    在服务阶段,每次请求都会调用`service()`方法,该方法会根据HTTP请求类型分派到`doGet()`或`doPost()`等具体处理方法。最后,当Servlet不再使用或者服务器关闭时,会调用`destroy()`方法释放资源,结束生命周期。 ...

    Java面试总结.pdf

    4. final的作用:final关键字在Java中用于声明类、方法和变量。当final用来修饰一个类时,表示这个类不能被继承;当用来修饰方法时,表示方法不能被重写;当用来修饰变量时,表示变量一旦赋值之后,其值就不能被修改...

    经典的Java Web 培训教材

    ### 经典的Java Web培训教材知识点概览 #### 一、前言和体系结构 在本章节中,教材详细介绍了Java Web应用的基础概念和技术框架,重点覆盖了以下几个方面: 1. **HTTP协议基础** - HTTP(HyperText Transfer ...

    net学习笔记及其他代码应用

    声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其...

    springmvc完整笔记附带说明代码.pdf

    Spring MVC是一个基于Java的实现MVC设计模式的请求驱动类型的轻量级Web框架,通过分离控制器、模型对象、分派器以及处理程序对象来提供Web层的模型设计。Spring MVC是Spring框架的一部分,它通过一套注解,让POJO...

    servlet 学习笔记

    4. 服务:每当有新的请求到达,Servlet容器会调用Servlet的`service()`方法,该方法会根据请求类型分派到`doGet()`或`doPost()`等具体方法。 5. 销毁:当服务器关闭或Servlet不再需要时,容器会调用Servlet的`...

    spring学习文档及源码笔记

    - **DispatcherServlet**:作为整个框架的入口点,负责接收请求并分派到相应的处理器。 - **Controller**:控制器处理用户请求,通常由开发者自定义,实现特定业务逻辑。 - **Model**:模型对象,包含了应用程序...

    javax.servlet-api:Java Servlet API规范规范原始代码阅读笔记

    2. **GenericServlet**:这是一个抽象Servlet类,实现了Servlet和ServletConfig接口,提供了基本的`service()`方法,可以根据请求类型分派到`doGet()`, `doPost()`等方法。 3. **HttpServlet**:进一步抽象了...

    SSH学习笔记.doc

    1. **DispatcherServlet**:所有请求由DispatcherServlet接收,它负责分派请求给合适的Controller。 2. **HandlerMapping**:找到处理请求的Controller。 3. **Controller处理**:Controller执行业务逻辑,返回...

    struts2的学习笔记+测试源代码

    Struts2是一个强大的Java web开发框架,用于构建和维护可扩展、优雅的MVC应用程序。这个学习笔记和测试源代码的资源着重于Struts2中的视图类型与全局视图的概念,以及结果类型转换和全局结果的配置。 首先,我们要...

Global site tag (gtag.js) - Google Analytics