繁体   English   中英

短生命对象中的长静态字符串

[英]long static Strings in short-lived objects

这可能是一个愚蠢的问题(或者只是让我看起来很愚蠢:)),但是我会对如何在短期对象的上下文中使用长String对象感兴趣。

考虑在cron作业或匿名,命令或类似函数的类中进行长SQL查询。 这些是非常短命的类,甚至在大多数时间里都会使用这些长字符串一次。 什么是更好的? 要构造一个String inline并让它与实例一起收集,或者将它设为静态final,并让它们在内存中无用,直到下一个类实例化为止?

好吧,对于字符串发生的事情,你只能控制得那么多。

即使你内联创建它,该String很可能会被添加到JVM的String常量池中,并且在你再次声明它时会被重用,所以在实践中,你可能会重用相同的String对象。

除非字符串太大以至于它对应用程序的性能产生影响,否则我不会担心它并选择对我来说更具可读性的选项。

如果该String仅在代码的一个特定点使用,在方法内部,我会将其声明为内联,我更喜欢将我的变量放在尽可能最小的范围内,但这里的意见可能会有所不同。 如果没有任何改变,并且在您的特定用例中似乎有意义,那么无论如何都要将String声明为静态,我怀疑它会影响性能。

字符串常量进入类的常量池,并且不能被优化掉,即处理得足够好。

创建长字符串并不是静态的。 对于SQL使用预处理语句? 占位符。 对于带有占位符的字符串也是如此:使用MessageFormat

要明确。 以下内容不需要额外费用:

static final String s = "... long string ...";

当剩余内存有限时,JVM通常会执行perm gen space清理和卸载未使用/未引用的类。 因此,在我看来,将长字符串作为静态变量不会造成太大的伤害

如果你觉得你的字符串可以占用大量内存,那么就不要使它们成为静态或使用String literal声明它们。 因为这两个都将存储在permgen空间中并且几乎完全被垃圾收集[有机会但是很小,静态可能永远不会被垃圾收集,因为你还没有创建自己的类加载器]。 因此,使用new运算符创建String,以便在堆中创建,并且可以轻松地进行垃圾收集,即

String str = new String("long string");

编辑:

字符串的存储方式: http//www.ntu.edu.sg/home/ehchua/programming/java/J3d_String.html

编辑:

关于新String如何工作,下面已经进行了长时间的讨论。 提出的参数是新的String将在堆中创建2个对象,在池中创建一个对象。 这是错误的,默认情况下不是这样,您可以通过调用intern方法强制java执行此操作。 为了支持我的参数,以下是来自Strin类的javadoc for intern方法:

实习生

public String intern()返回字符串对象的规范表示形式。 最初为空的字符串池由String类私有维护。

调用实习方法时,如果池已经包含等于此字符串对象的字符串(由equals(Object)方法确定),则返回池中的字符串。 否则,将此String对象添加到池中,并返回对此String对象的引用。

因此,对于任何两个字符串s和t,当且仅当s.equals(t)为真时,s.intern()== t.intern()才为真。

所有文字字符串和字符串值常量表达式都是实体。 字符串文字在Java语言规范的§3.10.5中定义

从上面的doc可以看出,如果新的String总是在池中创建一个对象,那么实习方法将完全无用!! 从逻辑上讲,它没有任何意义。

编辑:

另请阅读本文的答案: 字符串池为Java中的相同String创建两个字符串对象

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM