创建不可变对象,在没有新的情况下实例化 [重复]

Posted

技术标签:

【中文标题】创建不可变对象,在没有新的情况下实例化 [重复]【英文标题】:Create immutable object, instantiated without new [duplicate] 【发布时间】:2018-01-21 23:17:14 【问题描述】:

我可以创建一个只使用= 运算符进行实例化的类,就像String 类一样吗?或者这是 Java 中 String 类特有的功能?

【问题讨论】:

不,你不能。正如你所说,lies inside Java. 字符串=实例化。字符串常量是用"..." 定义的,它只会变得更加复杂。所以,不,你不能。使用new。如果你不喜欢new,你可以把它隐藏在静态工厂方法或类似的东西后面。 ***.com/questions/2068570/… 我的意思是如果我可以告诉 Java 如果我的班级旁边有“=”或“+=”该怎么办。我给了 String 类只是一个例子。不是 String 类的内部结构。我通过用户定义的运算符重载回复得到答案。谢谢大家。 @matthew - Java 实际上并没有对字符串中的“=”做任何特别的事情(它对“+=”有作用,但只是因为它对“+”有特殊的行为)。 【参考方案1】:

不,您不能创建仅使用 = 运算符实例化的类,因为您不能像在 C++ 或 C# 中那样在 Java 中重载运算符(见Operator overloading in Java)。

Strings 在您使用 "something" 时仅在它们不存在于内存中时才会被实例化,因此您每次编写 "something" 时都会获得对相同 String 对象的引用。

例如,如果你这样做:

String a = "something";
String b = "something";

然后

a == b; // will be true.

您可以查看这些问题以详细了解 String 对象的工作原理:

Strings are objects in Java, so why don't we use 'new' to create them?

What is the difference between "text" and new String("text")?

What is Java String interning?

【讨论】:

【参考方案2】:

由于 Java 不支持用户定义的运算符重载,因此无法使用 = 运算符创建新实例。

查看Why doesn't Java offer operator overloading?了解更多信息

【讨论】:

【参考方案3】:

代码String s = "Hello World!" 不会创建新的String。它将字符串池中存在的String 的引用分配给s。如果字符串池中不存在String,则在字符串池中创建一个新的String对象,但不是单独使用运算符=

这会创建新的String 对象:

String s1 = new String("Hello World!"); // new Object
String s2 = new String("Hello World!"); // new Object

System.out.println(s1 == s2); // false

这可能会也可能不会在字符串池中创建一个新的String 对象:

String s1 = "Hello World!";
String s2 = "Hello World!";

System.out.println(s1 == s2); // true

您可以通过使用getInstance() 模式获得与上述行为相当接近的情况,考虑一下:

public class Singleton 
  private Singleton()

  private static class SingletonHelper
    private static final instance INSTANCE = new Singleton();
  

  public static Singleton getInstance() 
    return SingletonHelper.INSTANCE;
  

那么你可以使用:

Singleton s = Singleton.getInstance();

【讨论】:

第一个代码sn -p 不一定会在字符串池中新建Stringnew String(...)创建的字符串不包含在池中)。 @Nevay 你当然是对的,我的错,纠正了我的答案。

以上是关于创建不可变对象,在没有新的情况下实例化 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何创建一个不允许重复实例的类(在可能的情况下返回现有实例)?

第6项:避免创建不需要的对象

设计模式:单例模式

为什么我不能在没有完整命名空间的情况下从字符串中实例化新对象

如何在不选择模式配置参数的情况下使用 mongoose 在 MongoDB 模式实例化中的关联数组/对象中执行 foreach?

WCF反序列化如何在不调用构造函数的情况下实例化对象?