我说,我使用了一个包含大量数据的变量String data.我想以下列方式使用此字符串的一小部分:
this.smallpart = data.substring(12,18);
Run Code Online (Sandbox Code Playgroud)
经过几个小时的调试(使用内存可视化器)后,我发现对象字段smallpart记住了所有数据data,尽管它只包含子字符串.
当我将代码更改为:
this.smallpart = data.substring(12,18)+"";
Run Code Online (Sandbox Code Playgroud)
..问题解决了!现在我的应用程序现在使用很少的内存!
怎么可能?有谁能解释一下?我认为这个小部分一直在引用数据,但为什么呢?
更新: 如何清除大字符串呢?data = new String(data.substring(0,100))会做什么吗?
我是一个学习Java的C++人.我正在阅读Effective Java,有些事让我很困惑.它说从不写这样的代码:
String s = new String("silly");
Run Code Online (Sandbox Code Playgroud)
因为它会创建不必要的String对象 但相反它应该写成这样:
String s = "No longer silly";
Run Code Online (Sandbox Code Playgroud)
好吧到目前为止......但是,鉴于这个课:
public final class CaseInsensitiveString {
private String s;
public CaseInsensitiveString(String s) {
if (s == null) {
throw new NullPointerException();
}
this.s = s;
}
:
:
}
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
Run Code Online (Sandbox Code Playgroud)
为什么第一个陈述好吗?不应该
CaseInsensitiveString cis = "Polish";
我如何使CaseInsensitiveString行为String如此上述声明是可以的(有和没有扩展String)?它是什么让它能够传递像这样的文字?根据我的理解,Java中没有"复制构造函数"概念?
是什么区别String str = new String("SOME")和String str="SOME"
是否这些声明给人的性能变化.
如果不可变类对象副本将等于原始副本那么为什么StringJava 中的类具有复制构造函数?这是一个错误还是这个实施背后的原因?在Java文档中,它被指定为:
/**
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param original
* A {@code String}
*/
public String(String original) {
....
....}
Run Code Online (Sandbox Code Playgroud) 实例化对象时,为什么要指定该类两次?
OddEven number = new OddEven();
Run Code Online (Sandbox Code Playgroud)
你为什么不能说出来number = new OddEven();?当我声明一个字符串时,我只说String一次:
String str = "abc";
Run Code Online (Sandbox Code Playgroud)
实际上,我的问题不是"为什么你这样做" - 显然,你这样做是因为你必须 - 但是,为什么创作者选择让Java语法像这样工作呢?
我的想法是:
我读过文章和书籍,String s = new String("...");应该尽可能避免使用.我明白为什么会这样,但是使用String(String)构造函数有什么用处吗?我不认为有,也没有看到任何其他证据,但我想知道SO社区中是否有人知道有用.
确切重复: java中表达新字符串的目的是什么?
public class Comparison {
public static void main(String[] args) {
String s = "prova";
String s2 = "prova";
System.out.println(s == s2);
System.out.println(s.equals(s2));
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
true
true
Run Code Online (Sandbox Code Playgroud)
在我的机器上.为什么?不应该==比较对象引用相等?
这可能是一个愚蠢的问题(或者只是让我看起来很愚蠢:)),但是我会对如何在短期对象的上下文中使用长String对象感兴趣.
考虑在cron作业或匿名,命令或类似函数的类中进行长SQL查询.这些是非常短命的类,甚至在大多数时间里都会使用这些长字符串一次.什么是更好的?要构造一个String inline并让它与实例一起收集,或者将它设为静态final,并让它们在内存中无用,直到下一个类实例化为止?
我一直以为如果我这样做String s = "Hello World".substring(0, 5),那么我就得到一个新的字符串s = "Hello".Java API文档中也记录了这一点:"返回一个新字符串,它是该字符串的子字符串".
但当我看到以下两个链接时,我开始怀疑.
Java中表达"new String(...)"的目的是什么?
基本上,他们说如果我使用String s = "Hello World".subString(0, 5),我仍然得到一个String,其中包含"Hello World"的char数组.
为什么?Java是否真的以这种方式实现了子串?为什么这样?为什么不返回一个全新的更短的子串?
我知道对于Oracle Java 1.7更新6及更高版本,在使用时String.substring,会复制String的内部字符数组,对于旧版本,它将被共享.但我发现没有官方API可以告诉我当前的行为.
我的用例是:在解析器中,我喜欢检测是String.substring复制还是共享底层字符数组.问题是,如果字符数组是共享的,那么我的解析器需要明确地"取消共享" new String(s)以避免内存问题.但是,如果String.substring无论如何都要复制数据,那么这不是必需的,并且可以避免在解析器中显式复制数据.使用案例:
// possibly the query is very very large
String query = "select * from test ...";
// the identifier is used outside of the parser
String identifier = query.substring(14, 18);
// avoid if possible for speed,
// but needed if identifier internally
// references the large query char array
identifier = new String(identifier);
Run Code Online (Sandbox Code Playgroud)
基本上,我想有一个静态方法boolean isSubstringCopyingForSure(),可以检测是否new String(..)不需要.如果检测不起作用,我没关系SecurityManager.基本上,检测应该是保守的(为了避免内存问题,我宁愿使用,new String(..)即使没有必要). …
java ×10
string ×6
coding-style ×1
ibm-jvm ×1
jvm ×1
memory ×1
performance ×1
syntax ×1
types ×1