【问题标题】:Can a Java constructor return already existing object of same type?Java构造函数可以返回已经存在的相同类型的对象吗?
【发布时间】:2016-04-22 02:01:07
【问题描述】:

每当我们在 Java 中调用构造函数时,它都会创建一个新对象并在最后(新创建的对象)返回其引用。

Java 构造函数是否有可能不创建新对象,而是返回对已创建对象的引用?

// Is it possible that myObject is not a new object, its already existing object
MyClass myObject = new MyClass();

我有一个类的对象列表,并且基于构造函数中的几个参数,有时我不创建新对象更有效,而是选择一个已经存在的对象。有没有其他办法?

【问题讨论】:

  • 一句话,没有。这个问题的起源是什么?
  • 不,这是不可能的。但是可以使用对象池或使用创建模式并重用以前创建的对象。
  • 只是想让程序更高效,不想使用池。我想可能会有类似的东西。
  • 创建一个私有构造函数和一个静态方法,该方法扮演您要创建的对象的工厂角色。然后,如果您需要创建一个新对象,请调用构造函数并返回其结果(新对象)。如果您不需要新对象,则返回一个已存储在某个静态变量中的现有对象。

标签: java oop object constructor new-operator


【解决方案1】:

没有。根据定义,构造函数在创建新对象以对其进行初始化时运行。如果构造函数被运行,一个新对象已经存在,你无能为力。

你可以做的是创建一个静态方法,它要么创建一个新对象,要么返回一个现有对象。这是这种情况下的标准方法。

说,标准库中的Boolean.valueOf(boolean value) 的存在是为了避免创建额外的对象。您可以使用new Boolean(value) 创建它们,但调用此方法要好得多,因为它会为相同的值返回相同的对象。

【讨论】:

    【解决方案2】:

    你不能使用构造函数来做到这一点,但你可以使用下面提到的模式之一。

    如果您只需要 1 个对象,请使用 Singleton 模式。

    如果您可能有一些变化,请使用Flyweight 模式,如 duffymo 所述。

    正如 duffymo 在下面的评论中提到的那样——如果你使用这些模式中的任何一种,那么从并发的角度来看,理解这些对象将是全局状态很重要——因此,你应该确保它们是不可变的,如果你不能使它们不可变那么您可能需要重新考虑您的方法。

    【讨论】:

    • 请不要使用单例模式。这是一个全局变量。谷歌已经竭尽全力从他们的代码中删除 Singleton。你也应该。 code.google.com/p/google-singleton-detector/wiki/…
    • 好叫 duffymo。但是,如果您采取措施确保它们是不可变对象,这些模式是安全的 - 但并不总是适合。
    • 不,全局变量不是一个好主意。假定线程安全。
    • 不假设您知道如何使对象真正不可变。但是,如果您对 Java 不是很熟悉,那么这是避免使用全局变量的好方法。
    • 我了解线程安全。我也明白为什么全局变量不是一个好主意,所以我不会推荐 Singleton。
    【解决方案3】:

    不,这是不可能的。

    JLS section 15.9:

    不合格的类实例创建表达式以关键字new开头。

    一个不合格的类实例创建表达式可用于创建一个类的实例,无论该类是顶级(§7.6)、成员(§8.5、§9.5),本地(§14.3)或匿名类(§15.9.5)。

    和JLS section 12.5:

    当评估类实例创建表达式(第 15.9 节)导致类被实例化时,显式创建一个新类实例。
    ...
    就在返回新创建对象的引用作为结果之前,使用以下过程处理指示的构造函数以初始化新对象:[...]

    请注意,这清楚地提到了对象的创建,而不是可能的再利用。


    另一方面,您可以为使用池的对象创建一个静态工厂。例如,您可以查看Integer.valueOf(i) 的实现。 Refer to this answer for example.

    【讨论】:

      【解决方案4】:

      您无法仅使用 Java 中的构造函数来实现此目的。

      如果需要,可以通过使用类内的静态方法(如Integer.valueOf(0))或不同类的整个专用对象(如DocumentBuilderFactory)返回实例来实现这种行为。这提供了足够的控制来替换现有对象,而不是总是创建一个新对象。

      作为一项规则,此类对象应该是不可变的并且线程安全以便于轻松共享。此外,实例重用和有时缓存也是按照这些思路实现的。

      【讨论】:

        【解决方案5】:

        没有。类提供对象的蓝图,当使用new 运算符时,它会调用构造函数,初始化新对象。 Source.

        如果您出于任何原因希望重用对象,您可能需要考虑在您的项目中实现 Flyweight pattern 和 Factory pattern 以获得最佳效果。

        【讨论】:

          【解决方案6】:

          不,这是不可能的。根据需要的逻辑创建一个静态方法来创建对象,不要忘记将构造函数设为私有。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-01-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多