java获取静态类_Java中获得当前静态类的类名

So, we have a situation when we need to statically get class object or a class full/simple name without an explicit usage of MyClass.class syntax.

It can be really handy in some cases, e.g. logger instance for the NT6zO.pngkotlin upper-level functions (in this case kotlin creates a static Java class not accessible from the kotlin code).

We have a few different variants for getting this info:

new Object(){}.getClass().getEnclosingClass();

noted by Tom Hawtin - tackline

getClassContext()[0].getName(); from the SecurityManager

noted by Christoffer

new Throwable().getStackTrace()[0].getClassName();

by count ludwig

Thread.currentThread().getStackTrace()[1].getClassName();

from Keksi

and finally awesome

MethodHandles.lookup().lookupClass();

from Rein

I've prepared a jmh benchmark for all variants and results are:

#Runcomplete.Totaltime:00:04:18BenchmarkModeCntScoreErrorUnitsStaticClassLookup.MethodHandles_lookup_lookupClassavgt 303.630±0.024ns/op

StaticClassLookup.AnonymousObject_getClass_enclosingClassavgt 30282.486±1.980ns/op

StaticClassLookup.SecurityManager_classContext_1avgt 30680.385±21.665ns/op

StaticClassLookup.Thread_currentThread_stackTrace_1_classNameavgt 3011179.460±286.293ns/op

StaticClassLookup.Throwable_stackTrace_0_classNameavgt 3010221.209±176.847ns/op

Conclusions

Best variant to use, rather clean and monstrously fast.

Available only since Java 7 and Android API 26!

MethodHandles.lookup().lookupClass();

In case you need this functionality for Android or Java 6, you can use the second best variant. It's rather fast too, but creates an anonymous class in each place of usage :(

newObject(){}.getClass().getEnclosingClass();

If you need it in many places and don't want your bytecode to bloat due to tons of anonymous classes – SecurityManager is your friend (third best option).

But you can't just call getClassContext() – it's protected in the SecurityManager class. You will need some helper class like this:

// Helper classpublicfinalclassCallerClassGetterextendsSecurityManager{privatestaticfinalCallerClassGetterINSTANCE =newCallerClassGetter();privateCallerClassGetter(){}publicstaticClass>getCallerClass(){returnINSTANCE.getClassContext()[1];}}// Usage example:classFooBar{staticfinalLoggerLOGGER =LoggerFactory.getLogger(CallerClassGetter.getCallerClass())}

You probably don't ever need to use last two variants based on the getStackTrace() from exception or the Thread.currentThread(). Very inefficient and can return only the class name as a String, not the Class instance.

P.S.

If you want to create a logger instance for static kotlin utils (like me :), you can use this helper:

importorg.slf4j.Loggerimportorg.slf4j.LoggerFactory// Should be inlined to get an actual class instead of the one where this helper declared// Will work only since Java 7 and Android API 26!@Suppress("NOTHING_TO_INLINE")inlinefun loggerFactoryStatic():Logger=LoggerFactory.getLogger(MethodHandles.lookup().lookupClass())

Usage example:

privateval LOGGER =loggerFactoryStatic()/**

* Returns a pseudo-random, uniformly distributed value between the

* given least value (inclusive) and bound (exclusive).

*

* @param min the least value returned

* @param max the upper bound (exclusive)

*

* @return the next value

* @throws IllegalArgumentException if least greater than or equal to bound

* @see java.util.concurrent.ThreadLocalRandom.nextDouble(double, double)

*/fun Random.nextDouble(min:Double=.0,max:Double=1.0):Double{if(min >=max){if(min ==max)returnmax

LOGGER.warn("nextDouble: min $min > max $max")returnmin

}returnnextDouble()*(max -min)+min

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值