在非静态方法中定义的字符串值会和类对象一起被垃圾收集吗



我有一组巨大的帮助文本,我想在课堂上对其进行硬编码。假设我们有不同国家的枚举,我可以创建具有方法的HelpTextInterface

public interface HelpTextInterface {
public String getText(CountryEnum enum);
}

以及HelpTextAsiaEnglish、HelpTextEuropeEnglish、帮助非洲英语、帮助亚洲印地语等子类

public class HelpTextAsiaEnglish implements HelpTextInterface {
public String getText(CountryEnum country) {
switch(country) {
case CHINA:
return "large text about china in english";
case JAPAN:
return "large string about japan in english";
.....
.....
.....
}
}
}

我可以根据国家和地区调用相应的HelpText提供程序类。这样就不会一次将所有文本加载到内存中。只有属于特定国家的类才会被加载。我的问题是,如果我重新分配HelpTextInterface类型的变量,作为方法一部分的字符串是否也会被垃圾收集或与类对象一起从内存中删除?例如

A. HelpTextInterface ht =  new HelpTextAsiaEnglish();
B. ht.getText(CountryEnum.INDIA);
.........
C. ht = new HelpTextAfricaHindi();

问题1:在步骤A或步骤B,属于所有亚洲国家的英语字符串何时会加载到内存中?

查询2:由于HelpTextAsiaEnglish()对象不再被引用,属于所有亚洲国家的英语字符串在步骤C后会被垃圾收集吗?困惑在于classloader,我不确定它是否会在步骤C之后卸载类HelpTextAsianEnglish。

查询3:我的目标是确保一次只在内存中加载一组字符串,有没有更好的方法可以做到这一点,比如让这些字符串成为成员变量。

这取决于实现细节,但引用实现HotSpot/OpenJDK将保留对代表文本的String实例的引用,一旦代码访问了它们,至少只要代码可以访问。

只要ClassLoader是可到达的,类就保持可到达,而ClassLoader只要其至少一个类是可访问的,就保持可访问。因此,因为很明显,HelpTextInterface实现是通过同一个类加载器定位的,所以一旦它们被加载,它们都将保持可访问状态。

由于它是针对具体实施的,它可能比这更糟糕。不同的JVM实现可以在加载类之后立即实例化该类的所有字符串。


创建仅以返回字符串为目的的类没有多大意义,尤其是在假设需要重新加载它们的情况下。您应该在代码库中创建文件,并通过getResource等读取它们。这些字符串与代码无关,可以正常进行垃圾收集。或者使用,例如PropertyResourceBundle,它已经达到了这个目的,并为文本定义的资源提供了Java接口。

相关内容

最新更新