当前位置: 首页 > 面试题库 >

“ this”关键字:Java中的工作机制

陈法
2023-03-14
问题内容

学习Java一段时间后,第一次使用this关键字就让我非常困惑。

这就是我的困惑。我写了以下代码:

class BasicInheritanceTest3Base{
    private int x = 0;
    public int y;

    public void a() {
        x++;
        this.x++;
        System.out.println("BasicInheritanceTest3Base.a()");
        b();
        this.b();
        System.out.println(x);
        System.out.println(y);
    }

    public void b(){
        System.out.println("BasicInheritanceTest3Base.b()");
    }
}

public class BasicInheritanceTest3 extends BasicInheritanceTest3Base {
    private int x = 3;
    public int y = 2;

    public void b() {
        System.out.println("BasicInheritanceTest3.b()");
    }

    public static void main(String[] args){
        BasicInheritanceTest3 bit2 = new BasicInheritanceTest3();
        bit2.a();
    }
}

我得到以下输出:

BasicInheritanceTest3Base.a()
BasicInheritanceTest3.b()
BasicInheritanceTest3.b()
2
0

现在,这里的第一个问题是:为什么xthis.x指向x基类而不是Child类?而且如果this.x指向x基类的,为什么要this.b()调用b()子类的?字段和方法的行为是否有所不同?

但是,主要关注的是this关键字的机制。我的意思是,您知道this(指向)当前对象。如果您考虑一下,这不是魔术行为。在this某处一定有田野。例如,.class类的文字是不可见的,但存在于发出的字节码中。同样,该引用应出现在字节码中。

好吧,假设以上是正确的,this应该是一个public final(空白的最终结果),它在每次构造对象及其字段时都被实例化。这意味着它是一个实例变量而不是静态变量。

现在,如果将其实例化为当前对象的引用(仅是特定的对象),那么this字段和方法在上面的用法又有何不同?总而言之,背后的机制是this什么?该机制是否也适用于super关键字?

编辑: 每个人都阅读问题,然后评论,我想问一下,this编译器在哪里声明了字段,其限定符是什么。结果行为在幕后如何发生?


问题答案:

其他答案和评论已经说明了字段不是多态的,以及如何根据实例引用的编译时类型解析字段访问表达式。下面,我解释字节码如何处理this引用。

在关于 接收参数
的章节中,Java虚拟机规范指出

如果将n个参数传递给实例方法,则按照惯例,它们是在为新方法调用创建的框架的编号为1到n的局部变量中接收的。参数按传递顺序接收。例如:

int addTwo(int i, int j) {
    return i + j;
}

编译为:

Method int addTwo(int,int)
0   iload_1        // Push value of local variable 1 (i)
1   iload_2        // Push value of local variable 2 (j)
2   iadd           // Add; leave int result on operand stack
3   ireturn        // Return int result

按照约定,实例方法将在局部变量0中传递对其实例的引用。在Java编程语言中,可通过this关键字访问实例。

类(静态)方法没有实例,因此对于它们而言,不需要使用局部变量0。一个类方法从索引0开始使用局部变量。如果addTwo方法是一个类方法,则其参数将以与第一个版本相似的方式传递:

static int addTwoStatic(int i, int j) {
    return i + j;
}

编译为:

Method int addTwoStatic(int,int)
0   iload_0
1   iload_1
2   iadd
3   ireturn

唯一的区别是方法参数从局部变量0而不是1开始出现。

换句话说,您可以将其this视为未在任何地方声明或被声明为每个实例方法的第一个参数。为每个实例方法创建一个局部变量表条目,并在每次调用时填充该条目。

关于
调用方法

的章节说明

实例方法的常规方法调用将分派对象的运行时类型。(使用C
++术语,它们是虚拟的。)这样的调用是使用invokevirtual指令实现的,该指令以运行时常量池条目的索引作为其参数,给出对象的类类型的二进制名称的内部形式,要调用的方法的名称,以及该方法的描述符(第4.3.3节)。要调用addTwo先前定义为实例方法的方法,我们可以编写:

int add12and13() {
    return addTwo(12, 13);
}

编译为:

Method int add12and13()
0   aload_0             // Push local variable 0 (this)
1   bipush 12           // Push int constant 12
3   bipush 13           // Push int constant 13
5   invokevirtual #4    // Method Example.addtwo(II)I
8   ireturn             // Return int on top of operand stack;
                        // it is the int result of addTwo()

通过首先将对当前实例的引用推this入操作数堆栈来建立调用。然后将方法调用的参数(int值12和13)推送。addTwo创建该方法的框架时,传递给该方法的参数将成为新框架的局部变量的初始值。
也就是说,this由调用者将对的引用和两个参数推入操作数堆栈,它们将成为被调用方法的局部变量0、1和2的初始值。



 类似资料:
  • 问题内容: 在下面的代码片段中,结果确实令人困惑。 结果是 为什么“ this”在父亲构造函数中指向Son,而“ this.x”却指向父亲在构造函数中的“ x”字段。“ this”关键字如何运作? 我知道 多态的 概念,但是[1]和[2]之间没有区别吗?触发 新的Son() 时,内存中发生了什么? 问题答案: 默认情况下,所有成员函数在Java中都是多态的。这意味着当您调用this.toStrin

  • 问题内容: “ this”关键字如何工作? 问题答案: [§11.1.1]的关键字 所述关键字的计算结果为当前执行上下文的ThisBinding的值 这个绑定是JavaScript解释器在评估JavaScript代码时所维护的,例如特殊的CPU寄存器,其中包含对对象的引用。每当在以下三种情况之一中建立执行上下文时,解释器都会更新ThisBinding: 1.初始全局执行上下文 在顶级代码中评估的J

  • 主要内容:this.属性名,this.方法名,this( )访问构造方法this 关键字是 Java 常用的关键字,可用于任何实例方法内指向当前对象,也可指向对其调用当前方法的对象,或者在需要当前类型对象引用时使用。 下面我们根据示例分别讲解 this 关键字的作用。 this.属性名 大部分时候,普通方法访问其他方法、成员变量时无须使用 this 前缀,但如果方法里有个局部变量和成员变量同名,但程序又需要在该方法里访问这个被覆盖的成员变量,则必须使用 this 前缀

  • 问题内容: 我刚刚遇到了一个有趣的JavaScript情况。我有一个类,该类的方法使用对象文字表示法定义了多个对象。在这些对象内部,正在使用指针。从程序的行为,我推断出指针是指向在其上调用方法的类,而不是由文字创建的对象。 尽管这是我期望的工作方式,但这似乎是任意的。这是定义的行为吗?跨浏览器安全吗?是否有任何推理依据说明它超出了“规格说明”的范围(例如,这是某些更广泛的设计决策/理念的结果)吗?

  • 本文向大家介绍“ this”关键字在JavaScript中如何工作?,包括了“ this”关键字在JavaScript中如何工作?的使用技巧和注意事项,需要的朋友参考一下 在JavaScript中,此关键字用作引用,以引用执行的代码的对象或主题。 示例

  • 问题内容: 我从Android开发者网站复制了以下代码: 我想知道“这个”关键字到底指的是什么?它是否引用了类“ ExampleActivity”?通常,如何找到“ this”指的是什么? 问题答案: 它是指的实例,其上被调用。 通常,从Java语言规范15.8.3开始: 关键字this只能在实例方法,实例初始值设定项或构造函数的主体中,或在类的实例变量的初始值设定项中使用。如果它出现在其他任何地