Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 静态最终字符串=";“什么?”静态有意义吗?_Java_String_Immutability_Object Pooling - Fatal编程技术网

Java 静态最终字符串=";“什么?”静态有意义吗?

Java 静态最终字符串=";“什么?”静态有意义吗?,java,string,immutability,object-pooling,Java,String,Immutability,Object Pooling,我想知道这样的声明在Java中是否有某种意义。我在代码中发现了数千次,但我学习和使用字符串时发现,无论您声明了多少次String对象:如果您之前的某个类声明了该字符串,则该字符串将被合并和重用(我指的是在没有显式构造函数调用的情况下创建的字符串) 实际上,这段代码在调用compare时打印true,因此这两个变量引用的是同一个对象。表示不能重新定义final变量,在这种情况下,静态字是完全无用的。我没抓住重点吗 还有几件事: 1-为什么显式调用String构造函数不会导致字符串合并?使用新字符串

我想知道这样的声明在Java中是否有某种意义。我在代码中发现了数千次,但我学习和使用字符串时发现,无论您声明了多少次
String
对象:如果您之前的某个类声明了该字符串,则该字符串将被合并和重用(我指的是在没有显式构造函数调用的情况下创建的字符串)

实际上,这段代码在调用compare时打印
true
,因此这两个变量引用的是同一个对象。表示不能重新定义
final
变量,在这种情况下,
静态
字是完全无用的。我没抓住重点吗

还有几件事:

1-为什么显式调用
String
构造函数不会导致字符串合并?使用
新字符串(“hello”)
打印
false
,上面的代码相同

2-池行为是否保留给字符串?还有一些其他的不可变对象(比如BigInteger),但我认为它们不是池化的。。。为什么?

谢谢,
Carlo

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

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


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

这是因为
String=“hello”
String h
没有在堆中创建任何对象,这些对象都存储在
String常量池中,其中为
新字符串(“hello”)在堆中创建一个新对象,这样地址就会不同


检查详细信息

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

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

  • 问:为什么显式调用字符串构造函数不会导致字符串被合并?以上代码使用新字符串(“hello”)打印错误
  • 因为字符串池仅用于字符串文本,如JLS所述,调用构造函数并没有被归类为字符串文本

  • Q:池行为是否保留给字符串
    字符串池仅用于字符串文本,但当然还有其他缓存用于不同的用例。最明显的一点是用来优化int的自动装箱的int缓存。

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

    String x = "hello";
    String h = "hello";
    

    使用static,你只需使用
    Uris.GOOGLE
    而不是new
    Uris()。GOOGLE

    这个词“static”是让类访问而不是实例。我不得不说,你对“完全无用”有一个奇怪的定义。你的问题到处都是,您对static和final的关注与literal和
    新字符串之间的差异无关;字符串池的存在在很大程度上是另一个问题。@MarkRotterVeel我关心池和静态字,当引用池对象的变量被声明为final时。我不认为我的问题是“到处都是”,我只是想理解在一个集合的不可变对象/stringA static(final)是一个常量中发生了什么。也就是说:您为该字符串指定了一个标签,这样您就可以从整个程序中访问它,并且可以确保始终使用正确的值。从内存保护的角度来看,它可能是与文本相同的字符串对象,但这不是使用静态final常量的原因。我没有考虑字段访问,因为我经常发现变量声明为private。但是你的考虑是正确的,谢谢你的回答。关于可读性/意图的第1点,我同意:问题是关于运行时环境的——我仍然不理解只合并文本的决定,我将研究JLS,这背后可能有一些原因decision@CarloBertuccini在创建JLS时,字符串池存储在perm gen中。。那时候是在垃圾堆上,但从来没有垃圾收集过。由构造函数创建的内部字符串可能会破坏堆。现在,这些谓词已经不再是真的了,但是插入确实要付出代价,当前的语言设计让开发人员可以控制何时需要插入字符串,何时不需要。@CarloBertuccini进一步挖掘,您还会在java类文件中遇到常量池;您必须深入研究JVM规范才能找到它。回到那时,这就是字符串文字的作用域,以及字符串的自动插入。它提供了与纯解释语言协同工作的设计。
    
    String x = "hello";
    String h = "hello";
    
    public class Uris
    {
        public static final String GOOGLE = "http://google.com";
        public static final String BBC = "http://bbc.co.uk";
    }