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

曼尼斯·库玛·沙玛(Manish Kumar Sharma)

学习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编译器在哪里声明字段以及其限定符是什么。结果行为在幕后如何发生?

Sotirios Delimanolis

其他答案和注释已经说明了字段不是多态的,以及如何根据实例引用的编译时类型解析字段访问表达式。下面,我解释字节码如何处理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的初始值。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Java中的关键字“ of”

来自分类Dev

Java中的static关键字

来自分类Dev

Java中的Monitor and Synchronized关键字

来自分类Dev

欺骗Java中的private关键字

来自分类Dev

Java中的“ .class”关键字

来自分类Dev

Java中的子类和关键字this

来自分类Dev

Java中的Implements关键字

来自分类Dev

Java中易变的关键字用法

来自分类Dev

@interface 是 Java 中的关键字吗?

来自分类Dev

“ is”关键字如何工作?

来自分类Dev

“ this”关键字如何工作?

来自分类Dev

java中此关键字的显式作用域如何工作?

来自分类常见问题

Kotlin中的reified关键字如何工作?

来自分类Dev

最终关键字在Android中的工作方式

来自分类Dev

in`关键字在迭代器中如何工作?

来自分类Dev

在Swift中,“ let”关键字到底如何工作?

来自分类Dev

关键字USING在PostgreSQL中如何工作?

来自分类Dev

“ super()”关键字在列表理解中无法正常工作

来自分类Dev

给定关键字在Scala 3或dotty中如何工作?

来自分类Dev

Oracle中的Interval关键字如何工作?

来自分类Dev

在Swift中,“ let”关键字到底是如何工作的?

来自分类Dev

Canopy的IPython中的global关键字如何工作?

来自分类Dev

Dart中的“ with”关键字

来自分类Dev

OCaml中的“ as”关键字

来自分类Dev

js中的this关键字

来自分类Dev

Java中的关键字,类似于C中的定义

来自分类Dev

为什么“ this”关键字在Java中是final?

来自分类Dev

如何通过Java在IPersistentMap中查找Clojure关键字?

来自分类常见问题

Java中default关键字的目的是什么?