相关疑难解决方法(0)

Java中表达"new String(...)"的目的是什么?

在查看在线代码示例时,我有时会通过使用new运算符将String常量赋值给String对象.

例如:

String s;
...
s = new String("Hello World");
Run Code Online (Sandbox Code Playgroud)

当然,这与之相比

s = "Hello World";
Run Code Online (Sandbox Code Playgroud)

我不熟悉这种语法,也不知道目的或效果是什么.由于String常量通常存储在常量池中,然后以JVM处理String常量的任何表示形式存在,甚至还会在堆上分配任何内容?

java string

63
推荐指数
3
解决办法
2万
查看次数

Java - 常见问题

与其他平台一样,跟进这个问题似乎合乎逻辑:Java中常见的非明显错误是什么?似乎他们应该工作的事情,但不是.

我不会给出如何构建答案的指导,或者什么"太容易"被认为是一个问题,因为这就是投票的目的.

也可以看看:

java

50
推荐指数
19
解决办法
1万
查看次数

Java不是垃圾收集内存

我正在读取一个非常大的文件,并从每一行中提取一小部分文本.但是在操作结束时,我的内存很少.在读取文件后,垃圾收集器似乎无法释放内存.

我的问题是:有没有办法释放这段记忆?或者这是一个JVM错误?

我创建了一个SSCCE来证明这一点.它读取1 mb(由于16位编码而在Java中为2 mb)文件并从每行中提取一个字符(~4000行,因此应该是大约8 kb).在测试结束时,仍然使用了完整的2 mb!

最初的内存使用情况:

Allocated: 93847.55 kb
Free: 93357.23 kb
Run Code Online (Sandbox Code Playgroud)

读取文件后立即(在任何手动垃圾收集之前):

Allocated: 93847.55 kb
Free: 77613.45 kb (~16mb used)
Run Code Online (Sandbox Code Playgroud)

这是预料之中的,因为程序正在使用大量资源来读取文件.

然而,我垃圾收集,但不是所有的内存都被释放:

Allocated: 93847.55 kb
Free: 91214.78 kb (~2 mb used! That's the entire file!)
Run Code Online (Sandbox Code Playgroud)

我知道手动调用垃圾收集器不会给你任何保证(在某些情况下它是懒惰的).然而,这发生在我的大型应用程序中,其中文件几乎占用了所有可用内存,并且导致程序的其余部分尽管需要它而耗尽内存.这个例子证实了我怀疑从文件中读取的多余数据没有被释放.

以下是生成测试的SSCCE:

import java.io.*;
import java.util.*;

public class Test {
    public static void main(String[] args) throws Throwable {
        Runtime rt = Runtime.getRuntime();

        double alloc = rt.totalMemory()/1000.0;
        double free = rt.freeMemory()/1000.0;

        System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);

        Scanner in = new Scanner(new File("my_file.txt"));
        ArrayList<String> …
Run Code Online (Sandbox Code Playgroud)

java memory performance garbage-collection

12
推荐指数
2
解决办法
8741
查看次数

在Java中使用String(String)构造函数

我读过文章和书籍,String s = new String("...");应该尽可能避免使用.我明白为什么会这样,但是使用String(String)构造函数有什么用处吗?我不认为有,也没有看到任何其他证据,但我想知道SO社区中是否有人知道有用.


确切重复: java中表达新字符串的目的是什么?

java string coding-style

11
推荐指数
3
解决办法
3万
查看次数

Java如何存储字符串以及子字符串如何在内部工作?

class StringTesting {
    public static void main(String args[])
    {
        String str = "abcd";
        String str1 = new String("abcd");
        String str2 = str.substring(0,2);
        String str3 = str.substring(0,2);
        String str4 = str.substring(0,str.length());
        String str5 = str1.substring(0,2);
        String str6 = str1.substring(0,2);
        String str7 = str1.substring(0,str1.length());

        System.out.println(str2 == str3);
        System.out.println(str == str4);
        System.out.println(str5 == str6);
        System.out.println(str1 == str7);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我在java 1.6.0_27上得到的输出:

false
true
false
true
Run Code Online (Sandbox Code Playgroud)

有人可以解释输出.我知道Java区分存储在堆中的String和存储在String"common pool"中的String(可以是interned).在内部,他们的表现如何不同.它是如何改变子串算法的.请在适当的地方引用书籍/文章/博客等.

java string substring

9
推荐指数
1
解决办法
2万
查看次数

切片后释放字符串以进行垃圾收集的正确方法

根据这篇Go Data Structures文章,在Strings部分下,它指出采用一个字符串片段会将原始字符串保留在内存中.

"(另外,在Java和其他语言中有一个众所周知的问题,当你切割一个字符串来保存一小块时,对原始文件的引用会将整个原始字符串保留在内存中,即使只有少量仍然存在Go也有这个问题.我们尝试和拒绝的替代方案是使字符串切片如此昂贵 - 分配和副本 - 大多数程序都避免使用它.)"

所以如果我们有一个很长的字符串:

s := "Some very long string..."
Run Code Online (Sandbox Code Playgroud)

我们采取一小部分:

newS := s[5:9]
Run Code Online (Sandbox Code Playgroud)

s我们发布之前,原件不会发布newS.考虑到这一点,如果我们需要newS长期保留,但是s为垃圾收集发布,采取什么方法?

我想也许这个:

newS := string([]byte(s[5:9]))
Run Code Online (Sandbox Code Playgroud)

但我不确定这是否真的有用,或者是否有更好的方法.

string garbage-collection go slice

4
推荐指数
1
解决办法
488
查看次数

对象问题.是否使用构造函数?

我是Java的新手,我对使用构造函数有一些疑问:

Map<String, Object> map = new HashMap<String, Object>();
        map.put("one", new String("Hello"));//1
        map.put("two", "world");//2
Run Code Online (Sandbox Code Playgroud)

哪个陈述更加糟糕?有什么区别?哪一个是最好的?

java string object map

2
推荐指数
1
解决办法
104
查看次数

JVM能否更聪明地共享字符串数据?

看看这个测试

    String s1 = "1234";
    String s2 = "123";
    Field field = String.class.getDeclaredField("value");
    field.setAccessible(true);
    char[] value1 = (char[]) field.get(s1);
    char[] value2 = (char[]) field.get(s2);
    System.out.println(value1 == value2);
Run Code Online (Sandbox Code Playgroud)

它打印false,这意味着JVM为s1和s2保存两个不同的char数组.任何人都可以解释为什么s1和s2不能共享相同的char数组?似乎java.lang.String是为内容共享而设计的,不是吗?

注意:我不了解所有JVM.这是Oracle的Java HotSpot(TM)客户端VM 22.1-b02(JRE 1.7).

UPDATE

在另一方面,如果部分共享是罕见的(似乎这只是由String.substring创建字符串),那么为什么要把所有的字符串也有int countint offset领域?这是8个无用的字节.这不仅是尺寸,也是创作速度.对象越大,初始化时间越长.这是一个测试

    long t0 = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        new String("xxxxxxxxxxxxx");
    }
    System.out.println(System.currentTimeMillis() - t0);
Run Code Online (Sandbox Code Playgroud)

需要~200ms.如果我使用这个课程

class String2 {
    char[] value;
    String2(String2 s) {
        value = s.value;
    }
}
Run Code Online (Sandbox Code Playgroud)

大约需要140毫秒.

java string

0
推荐指数
1
解决办法
157
查看次数