本地字符串扫描器何时收集垃圾?
When does a local String Scanner get garbage collected?
假设我有一个 String s
并且我想通过 Builder 中的此方法使用 Scanner 遍历它:
private void scan(String s){
Scanner scanner = new Scanner(s);
while (scanner.hasNext()){
//do something
}
}
假设 s
是一个变量,是另一个 Object
的一部分。
public class Person{
String name;
//rest of code
}
现在假设这个对象存储在一个单例中,该单例存储数据以便在程序的生命周期内随时可用
public class Singleton{
private List<Person> list = new ArrayList<>();
//rest of code
}
我的问题是:一旦 scan(String s)
完成 运行,scanner
会发生什么?它会继续存在还是会在达到其范围后被收集,从而释放资源?如果它没有被收集,如果我将 scan(String s)
更改为:
会发生什么
private void scan(String s){
Scanner scanner = new Scanner(s);
while (scanner.hasNext()){
//do something
}
scanner.close();
}
还是应该首选后一种形式?
始终首选关闭文件上的扫描程序,以便确定性地清理文件资源。
在 Scanner 被丢弃后可以清理字符串,假设它没有在其他任何地方被引用。
对于扫描器,我建议使用 try-with-resource
try (Scanner scanner = new Scanner(filename)) {
while (scanner.hasNext()){
//do something
}
}
在 String
上的 Scanner
的情况下,Scanner 将有一个 StringReader
作为其来源,它会引用字符串,但不会引用扫描仪本身。由于 StringReader 完全在内存中,因此不需要关闭或清理。关闭它没有什么坏处,但是,如果您确实选择关闭它,则应该将关闭调用放在 finally
块中,或者通过使用 try-with-resources:[=20 使其隐式调用=]
Scanner scanner = new Scanner(s);
try {
while (scanner.hasNext()) {
// do something
}
} finally {
scanner.close();
}
或:
try (Scanner scanner = new Scanner(s)) {
while (scanner.hasNext()) {
// do something
}
} // close will be implicitly called
规则是,您应该始终关闭您打开的任何内容以确保资源得到清理。
对于文件上的扫描程序,关闭它很重要。
对于 System.in
上的扫描程序,您没有 打开 System.in,因此您没有责任 [=34] =]关闭它。
对于字符串上的扫描器,或者从 ByteArrayInputStream
或 StringReader
读取时,没有任何有意义的资源需要关闭,但它可能最好以一种会调用 close 的方式编写内容,以防万一您稍后将其切换为从文件中读取(或只是为了养成习惯)。
对于你关于垃圾收集的问题,你永远不能说什么时候会被垃圾收集。如果您的程序永远不会 运行 内存不足,垃圾收集器甚至可能不会 运行。但是,由于 String 和 StringReader 都没有维护对 Scanner 的引用,因此当方法 scan(String)
returns.
假设我有一个 String s
并且我想通过 Builder 中的此方法使用 Scanner 遍历它:
private void scan(String s){
Scanner scanner = new Scanner(s);
while (scanner.hasNext()){
//do something
}
}
假设 s
是一个变量,是另一个 Object
的一部分。
public class Person{
String name;
//rest of code
}
现在假设这个对象存储在一个单例中,该单例存储数据以便在程序的生命周期内随时可用
public class Singleton{
private List<Person> list = new ArrayList<>();
//rest of code
}
我的问题是:一旦 scan(String s)
完成 运行,scanner
会发生什么?它会继续存在还是会在达到其范围后被收集,从而释放资源?如果它没有被收集,如果我将 scan(String s)
更改为:
private void scan(String s){
Scanner scanner = new Scanner(s);
while (scanner.hasNext()){
//do something
}
scanner.close();
}
还是应该首选后一种形式?
始终首选关闭文件上的扫描程序,以便确定性地清理文件资源。
在 Scanner 被丢弃后可以清理字符串,假设它没有在其他任何地方被引用。
对于扫描器,我建议使用 try-with-resource
try (Scanner scanner = new Scanner(filename)) {
while (scanner.hasNext()){
//do something
}
}
在 String
上的 Scanner
的情况下,Scanner 将有一个 StringReader
作为其来源,它会引用字符串,但不会引用扫描仪本身。由于 StringReader 完全在内存中,因此不需要关闭或清理。关闭它没有什么坏处,但是,如果您确实选择关闭它,则应该将关闭调用放在 finally
块中,或者通过使用 try-with-resources:[=20 使其隐式调用=]
Scanner scanner = new Scanner(s);
try {
while (scanner.hasNext()) {
// do something
}
} finally {
scanner.close();
}
或:
try (Scanner scanner = new Scanner(s)) {
while (scanner.hasNext()) {
// do something
}
} // close will be implicitly called
规则是,您应该始终关闭您打开的任何内容以确保资源得到清理。
对于文件上的扫描程序,关闭它很重要。
对于 System.in
上的扫描程序,您没有 打开 System.in,因此您没有责任 [=34] =]关闭它。
对于字符串上的扫描器,或者从 ByteArrayInputStream
或 StringReader
读取时,没有任何有意义的资源需要关闭,但它可能最好以一种会调用 close 的方式编写内容,以防万一您稍后将其切换为从文件中读取(或只是为了养成习惯)。
对于你关于垃圾收集的问题,你永远不能说什么时候会被垃圾收集。如果您的程序永远不会 运行 内存不足,垃圾收集器甚至可能不会 运行。但是,由于 String 和 StringReader 都没有维护对 Scanner 的引用,因此当方法 scan(String)
returns.