2013-02-22 102 views
9

Java字符串是不可变的,并且使用相同的值实例化多个字符串将返回相同的对象指针。 (这是否有一个术语?“池化”似乎适合,但这已经指的是通过执行更少的实例化来实现缓存以节省时间。)Java是否优化不可变对象?

Java是否也将此项目(没有术语的项目)与其他项目用户定义的)不可变的类? Java甚至可以检测到一个类是不可变的,或者这对于字符串类来说是独一无二的?

+0

+1有趣的问题。我相信Java可以识别只有最终成员的类,并将它们视为不可变的,但我没有关于这些的精确信息。我会关注这个问题。谢谢 – gd1 2013-02-22 09:24:39

+2

它没有,并考虑如果你反正改变了不可变对象,反射会发生什么.. – harold 2013-02-22 09:25:01

+0

我明白了,我对此有点惊讶。谢谢 – gd1 2013-02-22 09:25:35

回答

7

Wrt。字符串,你正在寻找的词是interning

Java不会为您自己的不可变对象执行此操作。不过,它确实缓存了盒装原语的版本。有关更多信息,请参见wrapper class caching上的这篇文章。

0

字符串实际内容仅适用于String类。我想JVM不会将这些规则应用于用户定义的类。

1

您正在查找的术语是itering。 Java在编译过程中“自动”优化字符串,并为开发人员提供了在运行时执行的可能性。 (根据JVM版本的不同,有关优化什么的细节)

至于它是否适用于不可变对象。我不认为Java支持任何可以解决相同情况的机制。字符串类型不是这个规则的豁免。

原因是,您是否必须使用运营商new来创建实例。如果您使用new创建字符串实例,您将始终获得两个不同的对象。

插入仅适用于字符串类型。但是这个概念是免费的,你可以将这种方法添加到你的不可变类中,并编写一个可以做同样事情的压缩方法。

2

正如其他人在这里所说的用Strings这个过程被称为实习。

其值得一提的字符串具有相同的文字值是相同对象的行为可能会或可能不会在Java 7中做到真正从7日起:

在JDK 7,实习字符串不再分配在Java堆的永久生成中,而是分配在Java堆的主要部分(称为年轻人和老年人)以及由应用程序创建的其他对象中。此更改将导致更多数据驻留在主Java堆中,永久生成中的数据更少,因此可能需要调整堆大小。由于这种变化,大多数应用程序在堆使用中只会看到相对较小的差异,但是加载很多类或大量使用String.intern()方法的较大应用程序将会看到更显着的差异。

查看Java SE 7 RFE了解详细信息。

关于你自己的不可变对象,Java并没有对它做任何特别的事情 - 它不知道它们是不可变的。它可能可能内联方法稍微超过否则,如果它可以检测到它的价值/可能,但就编译器和JVM而言,他们只是另一个对象。

+2

哇,downvoted?我可以采取downvote,但会很高兴知道为什么 – 2013-02-22 10:24:51