为什么Java构造函数不能同步?

2023-12-23

根据Java语言规范 http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.8.3,构造函数不能标记为同步,因为在创建该对象的线程完成之前,其他线程无法看到正在创建的对象。这看起来有点奇怪,因为我确实可以让另一个线程在构造对象时查看该对象:

public class Test {
    public Test() {
       final Test me = this;
       new Thread() {
           @Override
           public void run() {
               // ... Reference 'me,' the object being constructed
           }
       }.start();
    }
}

我知道这是一个非常人为的示例,但从理论上讲,似乎有人可以提出一种更现实的情况,其中将构造函数标记为同步是合法的,以防止与这样的线程发生竞争。

我的问题是:Java 是否有明确禁止在构造函数上使用同步修饰符的原因?也许我上面的例子是有缺陷的,或者也许真的没有理由,这是一个任意的设计决定。无论哪种情况,我都很好奇并且很想知道答案。


如果您确实需要同步构造函数的其余部分与任何获取对尚未完全构造的对象的引用的线程,则可以使用同步块:

public class Test {
    public Test() {
       final Test me = this;
       synchronized(this) {
          new Thread() {
             @Override
             public void run() {
                // ... Reference 'me,' the object being constructed
                synchronized(me) {
                   // do something dangerous with 'me'.
                }
             }
          }.start();
          // do something dangerous with this
       }
    }
}

通常,像这样“给出”尚未构造的对象被认为是不好的风格,因此不需要同步构造函数。


在某些极端情况下,同步构造函数会很有用。这是一个更现实的例子,来自 Bozho 答案的讨论:

public abstract class SuperClass {

   public SuperClass() {
       new Thread("evil") { public void run() {
          doSomethingDangerous();
       }}).start();
       try {
          Thread.sleep(5000);
       }
       catch(InterruptedException ex) { /* ignore */ }
   }

   public abstract void doSomethingDangerous();

}

public class SubClass extends SuperClass {
    int number;
    public SubClass () {
        super();
        number = 2;
    }

    public synchronized void doSomethingDangerous() {
        if(number == 2) {
            System.out.println("everything OK");
        }
        else {
            System.out.println("we have a problem.");
        }
    }

}

我们希望doSomethingDangerous()方法仅在子类对象的构造完成后调用,例如我们只想要“一切正常”的输出。但在这种情况下,当你只能编辑你的子类时,你就没有机会实现这一点。如果构造函数可以同步的话,问题就解决了。

因此,我们了解到:如果您的类不是最终类,则永远不要在超类构造函数中执行类似我在此处所做的操作 - 并且不要从构造函数中调用您自己的类的任何非最终方法。

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

为什么Java构造函数不能同步? 的相关文章

  • 如何为最终用户方便地启动Java GUI程序

    用户想要从以下位置启动 Java GUI 应用程序Windows 以及一些额外的 JVM 参数 例如 javaw Djava util logging config file logging properties jar MyGUI jar
  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • 如何使用 Java 和 Selenium WebDriver 在 C 目录中创建文件夹并需要将屏幕截图保存在该目录中?

    目前正在与硒网络驱动程序和代码Java 我有一种情况 我需要在 C 目录中创建一个文件夹 并在该文件夹中创建我通过 selenium Web 驱动程序代码拍摄的屏幕截图 它需要存储在带有时间戳的文件夹中 如果我每天按计划运行脚本 所有屏幕截
  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • Mockito when().thenReturn 不必要地调用该方法

    我正在研究继承的代码 我编写了一个应该捕获 NullPointerException 的测试 因为它试图从 null 对象调用方法 Test expected NullPointerException class public void c
  • 斯坦福 NLP - 处理文件列表时 OpenIE 内存不足

    我正在尝试使用斯坦福 CoreNLP 中的 OpenIE 工具从多个文件中提取信息 当多个文件 而不是一个 传递到输入时 它会给出内存不足错误 All files have been queued awaiting termination
  • 加密 JBoss 配置中的敏感信息

    JBoss 中的标准数据源配置要求数据库用户的用户名和密码位于 xxx ds xml 文件中 如果我将数据源定义为 c3p0 mbean 我会遇到同样的问题 是否有标准方法来加密用户和密码 保存密钥的好地方是什么 这当然也与 tomcat
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • Firebase 添加新节点

    如何将这些节点放入用户节点中 并创建另一个节点来存储帖子 我的数据库参考 databaseReference child user getUid setValue userInformations 您需要使用以下代码 databaseRef
  • JGit 检查分支是否已签出

    我正在使用 JGit 开发一个项目 我设法删除了一个分支 但我还想检查该分支是否已签出 我发现了一个变量CheckoutCommand但它是私有的 private boolean isCheckoutIndex return startCo
  • 按日期对 RecyclerView 进行排序

    我正在尝试按日期对 RecyclerView 进行排序 但我尝试了太多的事情 我不知道现在该尝试什么 问题就出在这条线上适配器 notifyDataSetChanged 因为如果我不放 不会显示错误 但也不会更新 recyclerview
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐

  • Excel VBA 日期之间的计数

    我需要创建一个函数来计算两个日期之间帐号的出现次数 第一个日期基于函数输入 第二个日期提前 3 个月 日期可能不包含在数据集中 该范围内的日期值的格式为 dd mm yyyy h mm 由于数据集的大小约为 150 000 行 我想在代码中
  • 从路径文件列表中列出Python中的目录树结构

    该问题旨在扩大 stackoverflow 上已通过主题 回答的问题的范围 python 中列出目录树结构 https stackoverflow com a 59109706 目标是形成一个直观地表示目录树的字符串列表 有分支机构 但输入
  • Scala 示例 - 具有上下文边界错误的特征类型参数?

    阅读 Scala by Example 一书 Martin 在第 54 页解释类型界限时有一个示例 trait Set A lt Ordered A def incl x A Set A def contains x A Boolean a
  • AngularJS 速溶咖啡资产控制器未找到

    在我的 AngularJS node js 中app https github com zishe angular express coffee基于角度表达博客 https github com btford angular express
  • 在弹性beanstalk部署的ec2微实例上创建交换文件/驱动器

    因此 只要我将应用程序放在比微型更大的实例上 它就可以很好地安装和部署 当我在 micro 上部署时 当作曲家尝试安装时 我收到一个有关无法分配足够内存的 php 错误 所以我做了一些谷歌搜索 似乎你可以在启动时创建交换文件 磁盘 创建实例
  • Shopware 6 在自定义主题中使用 fontawesome

    我需要在我的自定义主题中使用 fontawesome 因此我使用yarn安装了它yarn add fortawesome fontawesome free 当我尝试导入它时 import fortawesome 在我的主题的 base sc
  • javascript 中如何知道一个对象是否是 JSON? [复制]

    这个问题在这里已经有答案了 我如何知道变量是 JSON 还是其他变量 是否有 JQuery 函数或者我可以用来解决这个问题的东西 根据您的评论 听起来您不想知道字符串是否是有效的 JSON 而是想知道对象是否可以成功编码为 JSON 例如
  • 来自 Google Finance API 调用的 JSON 中的前导斜杠

    我一直在使用 Google Finance API 成功收集一些股票信息 问题是在调用之后http www google com finance info infotype infoquoteall q tickerSymbol Googl
  • JavaScript 中的 let 与 var [重复]

    这个问题在这里已经有答案了 我知道 let 具有块作用域 var 具有函数作用域 但我不明白在这种情况下 如何使用 let 来解决问题 const arr 1 2 3 4 for var i 0 i lt arr length i setT
  • 我的 JavaScript 模式/实践很糟糕。我应该去哪里寻求帮助?

    在过去的几年里 我几乎专门从事后端任务 我刚刚注意到 在我不在的情况下 大多数 JavaScript 和 CoffeeScript 项目都变得非常漂亮 我主要在 Rails 环境中工作 几乎所有的 JavaScript jQuery 过去都
  • gcloud 数据存储:我可以使用 IN 或 Contains 运算符进行过滤吗?

    我是数据存储区 gCloud 的新手 我想在一个名为 Score 的实体中过滤与公司列表相关的所有分数 我的实体的构成如下 company id 1 score 100 我有几个具有不同公司 ID 的实体 我尝试使用 query add f
  • 如何读取编码为utf-8的XML文件

    我正在尝试读取一个包含一些中文字符的 XML 文件 在将信息写入文件时 UTF 8编码可以正常工作 并且中文字符可以正确写入文件中 但是当我尝试阅读它时 它显示了一些 反而 我只是想知道是否有人已经遇到过这个问题并可以给我一些线索 首先 请
  • 当我将 Intellij 配置为缩进 2 个空格(更少)时,Intellij 缩进 4 个空格

    在 Intellij IDEA 14 上 我尝试在编辑器 gt 代码样式 gt LESS 中设置我的首选项以进行 2 个空格缩进 但无论我做什么 我的代码最终都会被格式化为 4 个空格缩进 如何让它以更少的速度缩进 2 个空格 如果您的项目
  • 具有整个程序范围的 using 指令

    我怎样才能有一个 using 指令 它的范围是整个程序 而不仅仅是它所在的文件 对于我使用的每个模块 我只想设置一次 如果没有办法做到这一点 有什么解决方法可以让它发挥作用 我想过将它们全部放入一个头文件中 但 C Sharp 没有文件包含
  • 在 Rails 范围内使用 devise_for 设计生成的邮件程序 URL

    我正在使用 Javascript 框架构建 Rails 应用程序 因此 Rails 正在为后端 API 提供服务 目前 该应用程序只是实现所有设计视图和操作 为此 Rails 应用程序仅接受对其的 JSON 调用 api URL 并要求 D
  • 从 Promise 内部返回已解析的 Observable

    我正在尝试通过扩展默认值来构建自定义 Angular 2 http 请求 并且我正在使用 Ionic 2 本地存储来存储身份验证令牌 将来可能会使用文件系统 我的问题是如何从我的 http 服务返回已解决的承诺 以便我可以在我的组件中订阅
  • 使用 graph_tool 的所有最短路径

    我想知道 graph tool 中是否有一个内置函数可以用来查找all从节点 s 到节点 t 的最短路径 如果没有 有什么方法可以使用shortest distance 在模块graph tool topology中 或shortest p
  • 时间:2019-03-17 标签:c#integervalidationcompactframework

    使用 Net Compact Framework 2 0 如何验证整数 Int32 TryParseCompact Framework 不支持 验证 是什么意思 你的意思是解析而不抛出 static bool TryParse string
  • 如何使用 php 从 HTML 中删除

    标签及其内容

    下面是我需要删除的文字 p 标签来自 p p Addiction stress and subjective wellbeing p p The need and significance of traditional shop lot p
  • 为什么Java构造函数不能同步?

    根据Java语言规范 http java sun com docs books jls third edition html classes html 8 8 3 构造函数不能标记为同步 因为在创建该对象的线程完成之前 其他线程无法看到正在