在Java中,新总是新的吗?

在Java中,新总是新的吗?,java,Java,在Java中,有没有什么方法可以像 Thing thing = new Thing(); 无法创建新对象(即,thing可能指向已存在对象的任何方式) new操作符分配新的堆空间并调用构造函数。您将始终以这种方式获得一个新对象(除非,如其他人所指出的,构造函数中抛出异常) 与返回引用的静态方法有些不同,例如Integer.valueOf(),如果可能,它会重新使用内部池中的对象。如果thing的构造函数抛出异常,则不会创建对象。然而,thing永远不会指向thing的另一个现有实例 否,如果内

在Java中,有没有什么方法可以像

Thing thing = new Thing();

无法创建新对象(即,
thing
可能指向已存在对象的任何方式)

new操作符分配新的堆空间并调用构造函数。您将始终以这种方式获得一个新对象(除非,如其他人所指出的,构造函数中抛出异常)


与返回引用的静态方法有些不同,例如
Integer.valueOf()
,如果可能,它会重新使用内部池中的对象。

如果thing的构造函数抛出异常,则不会创建对象。然而,
thing
永远不会指向thing的另一个现有实例

否,如果内存中没有空间容纳它,您应该得到一个OutOfMemoryError


当然,Thing构造函数可能会引发其他异常。

我不确定是否正确理解了您的问题

new的定义是分配和初始化一个新对象

我猜您可能可以存储对对象的静态引用,然后克隆它以生成新对象,但该对象仍然是新的


由于您无法修改
this
的值(否则您可以在构造函数中只说类似
this=oldObject
的话),因此唯一的方法是抛出异常,正如前面提到过的。

< P>我知道它不像C++那样可以超载<代码>运算符new <代码>或放置新的或其他分配器。(但我不熟悉JLS)

使用
new
将始终导致分配和创建新对象。但是,您可能指的是interning的概念,即对象和存储在池中,可以重用以节省空间。关于一个很好的例子,请参阅这篇关于Java的文章。

新总是新的(可能对原始包装器有一些例外),但是如果重用对象是一种理想的行为,那么可以通过某些设计模式(单例、工厂、池等)来实现这一点。

在Java中,我唯一能想到的就是使用单例模式。这不会创建多个新实例,而是每次都创建一个相同对象的实例。

有人说,如果构造函数抛出异常,就不会创建对象。我只想指出,事实并非如此。作为一个例子,请看一下这段非常糟糕的代码:

public class Test {
    static int count;

    static Set<Test> set = new HashSet<Test>();

    int id = count++;


    public Test() {
        set.add(this);
        throw new RuntimeException();
    }


    public static void main(String[] args) throws Exception {
        for(int i = 0; i < 5; i++) {
            try {
                new Test();
            } catch(Exception e) {
            }
        }
        System.out.println(set);
    }


    public String toString() {
        return "Test[" + id + "]";
    }
}

new
每次创建一个新对象。

new总是创建新对象。在java中,不能使用new重用对象。实际上,这会导致某些java类的性能问题。例如,布尔类实际上只能存储两个值(true或false),用户仍然可以使用new创建具有相同值的多个对象。


执行该行代码后,
thing
将永远不会引用该行之前存在的对象。

如果这是您第一次引用该类,并且该类具有无法初始化的静态块,则对
new
的调用可能会失败。我经历过这样的行为:静态块或构造函数中发生的任何运行时错误都会导致新调用在WebSphereApplicationServer中的使用上下文中抛出ClassNotFound异常。由于运行时异常,websphere类加载器显然拒绝加载该类。

为什么要问这个问题?你有什么奇怪的行为吗?没有。只是好奇-我在读关于Integer(int I)构造函数的书-重点是静态方法Integer.valueOf(int I)可能会更好,因为它会在必要时重用对象-我想检查构造函数是否不可能,而不仅仅是非常规的。是的,这是不可能的。在C++中,可以重写<代码>新< /Cord>操作符,但不能在java中使用。这并没有让我难过。@mmyers:在你必须实现类似Flyweight模式的东西之后再说一遍。重载运算符new()非常方便。不是我在十年的C++工作中必须这么做的。任何时候使用<代码>新< /C> >,你都在创建一个新的实例。时期使用单例模式,您调用的是
SingletonClass.getInstance()
,而不是
newsingletonclass()
。hmmm,为什么这不是OutOfMemoryError?只是有兴趣。@CD1@Tim纠正了错误。我知道是这样的。我的badYep甚至是伟大的Joshua Bloch的“有效Java”原语包装器(也称为盒装原语)中的推荐模式,它遵循与任何其他类相同的规则:如果您使用构造函数创建一个,您总是会得到一个新实例。然而,自动装箱不一定每次都创建一个唯一的对象,因为它使用工厂方法而不是构造函数。我说过什么不同的吗?新总是新的。没有例外,即使对于基本包装器也是如此。也没有
null
值。看到像
Thing t=newthing()这样的代码是很奇怪的;如果(t==null).
-这将永远不会发生
[Test[0], Test[1], Test[2], Test[4], Test[3]]