2
static final String = "something";

我想知道这样的声明在 Java 中是否具有某种真正的意义。我已经在代码中发现了数千次,但是学习和使用字符串我已经了解到,无论你声明一个对象多少次String:如果你之前的某个类声明了这个字符串,它就会被池化并重用(我是谈论在没有显式构造函数调用的情况下创建的字符串)

public class StringCompare {   
    private void toCompare(String h) {
        String x = "hello";
        System.out.println( x == h);
    }

    public void compare() {
        String h = "hello";
        toCompare(h);
    }      
}

事实上,这段代码在true调用 compare 时会打印出来,因此 2 个变量引用的是同一个对象。说final不能重新定义一个变量,这个static词在这种情况下完全没用。我错过了重点吗?

还有几件事:

1 - 为什么显式调用String构造函数不会导致字符串被池化?上面使用new String("hello")print的相同代码false

2 - 池行为是否保留给字符串?还有一些其他不可变对象(如 BigInteger),但我认为这些对象没有被合并……为什么?

谢谢,卡罗

4

5 回答 5

4

开发人员使用此模式有几个原因,即使您对运行时行为及其使用字符串池的分析是正确的。

  1. 它更清晰地传达了开发人员的意图。具体来说,字符串现在有一个希望比常量更清晰的名称,并且它传达了并非每个人都知道的运行时行为(或者他们不时忘记)。
  2. 如果开发人员想要更改源文件中的值,并且它已在多个地方使用,那么只有一个地方可以进行更改。
  3. 一旦决定使用变量,关键字 static 将意味着内存使用量较低。也就是说,只有一个字段用于存储 ref,而不是每个对象实例都有一个字段。

至于您的后续问题:

  1. 问:为什么显式调用 String 构造函数不会导致 String 被池化?上面的相同代码使用 new String("hello") print false。

因为字符串池仅用于字符串文字,如 JLS 所述,调用构造函数不属于字符串文字。

  1. 问:池化行为是否保留给字符串?

字符串池仅用于字符串字面量,但当然还有针对不同用例的其他缓存。最明显的想到的是用于优化 int 自动装箱的 int 缓存。

于 2014-10-03T09:56:56.217 回答
2

即使在这种情况下静态不会给您带来内存优势,您仍然可以以静态方式访问该字段,因此您不需要实例。例如,您经常使用一些 URI,因此您创建了以下类:

public class Uris
{
    public static final String GOOGLE = "http://google.com";
    public static final String BBC = "http://bbc.co.uk";
}

使用static,您可以只使用Uris.GOOGLE而不是 new Uris().GOOGLE

于 2014-10-03T09:59:08.197 回答
1

static意味着对于为该类创建的每个新对象,字符串构造和池只需要发生一次,永远。这节省了一点计算量。

于 2014-10-03T09:55:43.733 回答
1

这是因为String ="hello"String h没有在堆中创建任何对象,这些都存储在String constant poolnew String("hello");堆中创建新对象的位置,因此地址将不同

在此处查看详细信息

于 2014-10-03T09:56:32.550 回答
0
String x = "hello";
String h = "hello";

是两个字String面量。它们在公共池中(字符串池的一部分)。有参考相同的参考。然后==检查您将获得的参考资料true

如果使用String x = new String("hello"),它将创建一个新String对象x。当然是指新的参考。现在比较参考给你false

于 2014-10-03T09:55:56.510 回答