RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 560889
Accepted
Roxio0
Roxio0
Asked:2020-08-30 15:27:56 +0000 UTC2020-08-30 15:27:56 +0000 UTC 2020-08-30 15:27:56 +0000 UTC

获取对超类实例的引用

  • 772

我试图理解Java. 有一些代码:

class A {
    A getThis() {
    System.out.println("call getThis() from A");
    return this; //(3)
    } //(3)

    Object getSuper() {
    System.out.println("call getSuper() from A"); 
    return null;}
}

class B extends A {
    B getThis() {
    System.out.println("call getThis() from B"); 
    return this;
    }

    A getSuper() {
    System.out.println("call getSuper() from B"); 
    return super.getThis();
   }
}

class Tester {
    public static void main (String[] args) {
        Object a = new B().getSuper(); //(1)
        System.out.println(a);
        a = new B().getSuper().getSuper(); //(2)
        System.out.println(a);
    }
}

结果,控制台上显示以下文本:

从 B 调用 getSuper()

从 A 调用 getThis()

B@25154f

从 B 调用 getSuper()

从 A 调用 getThis()

从 B 调用 getSuper()

从 A 调用 getThis()

B@10dea4e

我预计当第 (1) 行被处理时,a类的一个实例将在 中A,而在第 (2) 行被处理后,a它将是null。为什么this从第 (3) 行返回的结果不是返回父类的引用,而是返回原始类的引用?


据我了解,当创建一个类的实例时B,它会存储对父类实例的引用A。我看到间接证实了我的话:

当调用类构造函数时B,类构造函数被调用A。即使在重写f类 B 中的方法时,您也可以通过;访问f类方法。 尽管如此,在处理类的实例时,我看不到一种方法可以从中返回对其中使用的类实例的引用。有什么办法可以使这成为可能吗?Asuper.f()
BA

java
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Best Answer
    privod
    2020-08-30T16:10:59Z2020-08-30T16:10:59Z

    我认为您混淆了类和对象的概念。

    类是一种描述实体的方式,它定义了依赖于该状态的状态和行为,以及与该实体(合约)交互的规则。

    对象(实例)是类的独立代表,具有完全由类定义的特定状态和行为。

    this关键字并不指向一个类,而是指向该类的一个实例(一个对象)。super 关键字提供对同一对象的属性和方法的访问,但在超类中进行了描述。

    例如:你创建了一个类的对象бирюса,Холодильник类Холодильник继承自类БытоваяТехника。对象бирюса既是冰箱又是家用电器。this 将返回对对象的引用бирюса,无论通过Холодильникor接收到哪个类的引用БытоваяТехника,对象都不会因此发生变化。

    所以你的对象a是类的一个实例,B同时它是类的一个实例А,因为它是从它继承的。当你在链中调用 getSuper() 方法时,this 作为结果返回,即对象的引用a

    类和对象定义取自此处。

    • 9
  2. Arhadthedev
    2020-08-31T01:51:16Z2020-08-31T01:51:16Z

    这个答案是针对这里涌入的“对超类的引用”的问题。它的措辞略有不同。


    1. 据我了解,当创建一个类的实例时B,它会存储对父类实例的引用A。

      不,它没有被存储。类的实例是类B的实例。为了更清楚,考虑一下继承机制是如何在 Java、C++ 和许多其他语言中实现的。A

      让类A定义如下:

      public class A
      {
          public int Foo;
          private short Bar;
      }
      

      然后此类的实例在内存中将具有以下形式:

      ref -> +-----------------------+
             | Внутренние данные JVM |
             +=======================+
             | Foo                   |
             +-----------------------+
             | Bar                   |
             +-----------------------+
      

      其中ref是对包含类实例数据的内存区域的引用。

      在上图中,可以看出两个特点:

      1. 类的公共和私有字段可以互换存储;访问修饰符仅在编译时检查字段访问的合法性时有效。
      2. Java 虚拟机将自己的内部数据存储在类本身的数据旁边。根据特定的虚拟机,这可以是:智能指针计数器、元信息链接或指向覆盖函数方法的指针表的链接。

      在继承的情况下:

      public class B extends A
      {
          public AnotherClass Foo2;
          private int Bar2;
      }
      

      属于父类的数据附加到属于子类的数据:

      ref -> +-----------------------+
             | Внутренние данные JVM |
             +=======================+
             | Foo                   |
             +-----------------------+
             | Bar                   |
             +=======================+
             | Foo2                  |
             +-----------------------+
             | Bar2                  |
             +-----------------------+
      

      这一大堆并指定了该类的一个实例B。您可以看到对它的引用与对类实例的引用完全相同A。因此,将链接提升到层次结构只是简单地重命名现有链接。

      “对父类实例的引用”用在真正引用的嵌套类中,但不只是引用父类,而是引用关闭类。

    2. 尽管如此,在处理 B 类的实例时,我看不到一种方法可以从它返回对其中使用的 A 类实例的引用。

      向上转换总是隐式地(自动地)完成:

      B foo = getFoo();
      A bar = foo;
      
      1. 当调用类构造函数时B,类构造函数被调用A。

      2. 即使您重写了类 B 中的方法 f,您也可以A通过super.f();访问类方法 f。

      所有这些魔法的发生都是因为虚拟机知道所有类的整个层次结构,因此它可以显式或隐式地替换对层次结构中向上的方法的调用。

    • 6
  3. Mikhailov Valentin
    2020-08-30T18:58:36Z2020-08-30T18:58:36Z

    为了理解为什么调用本类的方法时无法获取到基类实例的引用,在继承者中,需要了解调用继承方法在java中是如何工作的。

    首先,我们在内存中创建一个对象,其中包含从父对象继承的所有字段。并且这个对象可以通过一个链接访问,并且它不包含任何嵌套的父对象。this在调用构造函数A和时比较引用B。

    public A(){
        System.out.println(this);
    }
    public B(){
        System.out.println(this);
    }
    

    其次,实例方法与对象的字段分开存储,A甚至B通过类在对象上调用从类继承的方法А。但是当调用继承的方法时,它们会传递一个对调用它们的子实例的引用。因此,可以说,该方法是在所创建对象的实际实例上调用的。

    请注意,使用 invokespecial 指令调用的方法始终将 this 作为第一个参数传递给被调用的方法。

    • 4
  4. Ihor Savchenko
    2020-08-31T01:04:45Z2020-08-31T01:04:45Z

    在创建继承类B时类A的构造函数的调用是在JVM的工作级别执行的,并且只是为了初始化类B的对象的字段,无法通过编程方式获取此引用,因为 A 类不存在。但是如果 B 类是 A 类的内部类,那么它将存储对 A 类对象的引用。

    • -1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5