当基类构造函数调用Java中重写方法时派生类对象的状态

2024-04-21

请参考下面的Java代码:

class Base{
     Base(){
         System.out.println("Base Constructor");
         method();
     }
     void method(){}    
}

class Derived extends Base{
    int var = 2;
    Derived(){
         System.out.println("Derived Constructor");  
    }

     @Override
     void method(){
        System.out.println("var = "+var);
     }
 }

class Test2{
    public static void main(String[] args) {
        Derived b = new Derived();
    }
}

看到的输出是:

Base Constructor
var = 0
Derived Constructor

我认为 var = 0 发生是因为派生对象已半初始化;类似于什么乔恩斯基特在这里说 https://stackoverflow.com/questions/1511822/java-call-overridden-method-implicitly/1511836#1511836

我的问题是:

如果尚未创建派生类对象,为什么会调用重写的方法?

var 在什么时间点被赋值为 0?

是否有任何需要这种行为的用例?


  • The Derived object has已创建 - 只是构造函数尚未运行。在 Java 中,对象的类型在创建后就永远不会改变,这发生在所有构造函数运行之前。

  • var在运行构造函数之前,作为创建对象过程的一部分,被分配默认值 0。基本上,类型引用被设置,并且表示对象的其余内存被擦除为零(从概念上讲,无论如何 - 作为垃圾收集的一部分,它之前可能已经被擦除为零)

  • 这种行为至少会带来一致性,但也可能会很痛苦。就一致性而言,假设您有一个可变基类的只读子类。基类可能有一个isMutable()属性实际上默认为 true - 但子类覆盖它以始终返回 false。如果对象在子类构造函数运行之前是可变的,但在运行之后就不可变,那就很奇怪了。另一方面,它是确实奇怪的是,在类的构造函数运行之前,您最终在类中运行代码:(

一些指导方针:

  • 尽量不要在构造函数中做太多工作。避免这种情况的一种方法是在静态方法中进行工作,然后使静态方法的最后部分成为仅设置字段的构造函数调用。当然,这意味着您在执行工作时不会获得多态性的好处 - 但在构造函数调用中这样做无论如何都是危险的。

  • 尽力避免在构造函数期间调用非最终方法 - 这很可能会导致混乱。记录任何真正调用您的方法have使very显然,这样任何覆盖它们的人都知道它们将在初始化完成之前被调用。

  • 如果你必须在构造过程中调用一个方法,那就是usually之后调用它就不合适了。如果是这种情况,请记录下来并尝试在名称中注明。

  • 首先尽量不要过度使用继承——只有当您有一个从超类派生的子类而不是 Object 时,这才会成为问题:) 继承设计是很棘手的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当基类构造函数调用Java中重写方法时派生类对象的状态 的相关文章

  • 构建 jar 后无法运行 exe

    我制作了一个简单的实用应用程序 其中我有一个要运行的exe文件 我通过使用它来运行 Runtime getRuntime exec this getClass getResource filename exe getPath 当我从 ide
  • 为什么需要使用java.util.TimerTask的purge()?

    Timer cancel 取消任务 Timer purge 从此计时器的任务队列中删除所有已取消的任务 如果我不在这里使用 purge 会发生什么 当计时器的任务队列已满时会发生什么 除非您正在运行的计时器数量过多 否则实际计时器行为不会发
  • 访问 java jigsaw 模块中的资源文件[重复]

    这个问题在这里已经有答案了 我正在尝试从项目中的类访问 Eclipse 项目中的文件 我需要将该项目声明为 jigsaw 模块才能从其他项目访问它 但是通过这样做 我无法再访问项目中的 example png 等文件 这是我的项目结构 pr
  • Java RMI 通过互联网

    我正在用 Java 开发一个游戏 使用 RMI 进行所有网络通信 RMI 允许我调用服务器上的方法 但这对我来说还不够 我还希望服务器能够在连接的客户端之间传播消息 我的客户端查找服务器 它的接口扩展了远程 并在其上注册 它允许服务器知道谁
  • Spring Boot 是否支持服务器名称指示(SNI)?

    Spring Boot 是否支持服务器名称指示 SNI 具体来说 运行嵌入式 Tomcat 服务器并打包为可执行 jar 文件的 Spring Boot 2 2 2 RELEASE 应用程序是否可以根据传入请求的主机名支持多个 SSL 证书
  • Netflix Archaius 动态配置

    我正在将 Hystrix 集成到现有项目中 并且希望从 xml 文件中读取配置值 而不是使用配置管理器提供配置属性 当 xml 文件中的值更新时 我希望 Hystrix 配置在运行时更新 这是我遵循的指南 https github com
  • 无法在 Spring boot 中使用 findOne() 方法

    我的项目是关于用户管理器网络的 我是 Spring 和 Java 的新手 这是我的代码 在 UserController 中 RequestMapping value users name method RequestMethod GET
  • spring启动时如何加载@Cache?

    我正在使用 spring cache 来改进数据库查询 其工作原理如下 Bean public CacheManager cacheManager return new ConcurrentMapCacheManager books Cac
  • 正则表达式的替代(流畅?)界面设计

    我刚刚看到了一个巨大的 Java 正则表达式 这让我对正则表达式的一般可维护性进行了一些思考 我相信大多数人 除了一些糟糕的 Perl 贩子 都会同意正则表达式很难维护 我正在考虑如何解决这种情况 到目前为止 我最有希望的想法是使用流畅的界
  • 非法监控状态异常

    如何将轮询线程传递给另一个线程进行处理 程序执行在控制器类中 该类具有 main 方法和线程池 主类控制器 public static void main String args throws InterruptedException Ru
  • C++:重写由另一个方法调用的受保护方法

    我有一个关于 C 继承的非常基本的问题 class A public void foo print protected void print class B public A protected void print std cout lt
  • 如何正确安装mysqlconnecter java?

    上网冲浪后 我意识到我应该在系统环境变量中设置类路径连接器 jar 文件的路径文件我这样做了 并在命令行中输入此命令我有这个 C Users User gt echo classpath D classpath mysql connecto
  • 获取运行时提供的类名的 n 维数组的类

    给定一个完全限定的类名和多个维度 我想获取该类的类名 我相信我可以这样做 public Class elementType Class forName className return Array newInstance elementTy
  • 将 JAR 文件打包为 WAR 文件

    我有一系列依赖的Java项目 我想将它们打包成一个 JAR 文件 以便在我的 WAR 文件中使用 这些项目依赖于大量的外部库和项目 如log4j apache commons等 我选择 Eclipse 中的所有项目并导出为 JAR 文件 然
  • 使用 Hibernate 作为 ORM 机制的 Web 应用程序中的 L1 和 L2 缓存有什么区别?

    我只想要一些有关使用 L1 缓存和 L2 缓存的标准用途的一般信息 我很好奇 因为我正在研究使用赤土陶器作为二级缓存的系统 并且我发现它也有一级缓存 L1 缓存是每个 Hibernate 会话都存在的缓存 并且该缓存不在线程之间共享 该缓存
  • 如何在 groovy 中将输出重定向到 stderr?

    我正在寻找一种将 groovy 脚本中的输出重定向到 stderr 的方法 catch Exception e println Want this to go to stderr 就在我的脑海中 你不能做一些自我接线吗 def printE
  • Cordova Android 应用程序中的网页不可用

    编辑 我一直在解决这个问题并回顾我的所有步骤 我很乐意缩小这个问题的规模 并在令人困惑的情况下获得更多确切的细节 目前 我觉得 Keycloak 似乎只想将我重定向到 https 据我所知 这应该是 Wildfly 服务器配置问题 编辑 我
  • 如何找到类路径上具有特定方法注释的所有类?

    我想在Java中实现一个基于注释的初始化机制 具体来说 我定义了一个注释 Retention RetentionPolicy RUNTIME Target ElementType METHOD public interface Initia
  • java POI XSSF 公式评估器

    我在保存新的 Excel 文件时遇到问题 我希望当它被保存时 公式会自行计算 但目前它只是返回 Excel 文件中的一个字符串 公式是正确的 我不知道到底要得到FormulaEvaluator上班 这是我输入返回字符串的公式的地方 data
  • 使用服务器 java api 从 jasperserver 存储库检索资源

    我正在尝试使用其 java API 从 Jasperserver 存储库检索资源 根据jasper 报表服务器终极指南 https community jaspersoft com documentation jasperreports s

随机推荐