2011-08-18 40 views
9

在许多类项目的我的工作,我看到一个名为CLASS_NAME私有静态最后的成员,这是这样定义的:是否class.getName()很贵?

public class MyClass { 
    private static final String CLASS_NAME = MyClass.class.getName(); 
    //... 
} 

有什么好处,如果有的话,这样做是为了获取类的名称,而不是直接在需要名称的地方执行MyClass.class.getName()调用?

回答

10

这里是Class.getName()

public String getName() { 
if (name == null) 
    name = getName0(); 
return name; 
} 

执行正如你可以看到name的值被缓存,所以呼叫不是太昂贵了。它就像常规的getter一样。无论如何,如果你经常调用它,定义常量可能是一种很好的风格。

1

不,它并不昂贵。我能想到的唯一好处是IDE可以快速向您显示正在使用此特定常量的位置,而对于长类名称,常量会更短,使代码更清晰。

0

我们将不得不看到所有的代码,看看如何使用CLASS_NAME。但是,很可能在其他地方使用,比如你可以用的Log4J这样使用它:

// Log4j . Logger --- Get class name in static context by creating an anonymous Throwable and 
// getting the top of its stack-trace. 
// NOTE you must use: getClassName() because getClass() just returns StackTraceElement.class 
static final Logger logger = Logger.getLogger(new Throwable() .getStackTrace()[0].getClassName()); 

它不是一项昂贵的操作,并可能缓存。

6

缓存类名将带来另一个引用的开销。这改变了JVM操作码的成本(CPU复杂度)以适应内存占用。

现在的CPU速度非常快,基本上都是在内存上等待,所以如果你必须在操作码和内存占用之间做出选择,你最好选择通过JVM运行更多的操作码。

起初这似乎并不直观;但是,请考虑JVM和周围的硬件。较大的内存占用空间意味着缓存中最近访问的项目数量较少,重新获取超出缓存的项目成本大约是运行单个JVM操作码成本的1,000到10,000倍。将它与JVM的jit引擎结合起来,大量访问的代码块的CPU复杂性将得到优化(除其他所有内容外)。

所以,一般来说,我会通过不缓存引用来修剪对象,因为它可以让更多的对象被推入一级缓存。但是,像所有现实世界的性能调优一样,您应该测试以确定结果是否与假设相匹配,并且以不会被JVM的所有其他内部工作混淆的方式进行测试。

+0

这是一个很好的建议,谢谢! –

1

这并不昂贵。这似乎是一个用于记录目的的约定。

比较

logger.entering(CLASS_NAME, ...) 

logger.entering(MyClass.class.getName() ,...) 

除此之外,记录代码时复制到另一个来源将不会打破(记录错误的类)。