Java中获得当前静态类的类名
通常在打印日志的时候需要输出类名,普通类可以用this.getClass(),但是静态类没有this,直接写类名耦合度高。
参考了:
https://stackoverflow.com/questions/936684/getting-the-class-name-from-a-static-method-in-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
kotlin 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 theSecurityManager
noted by Christoffer
new Throwable().getStackTrace()[0].getClassName();
by count ludwig
Thread.currentThread().getStackTrace()[1].getClassName();
from Keksiand finally awesome
MethodHandles.lookup().lookupClass();
from ReinI've prepared a jmh benchmark for all variants and results are:
# Run complete. Total time: 00:04:18 Benchmark Mode Cnt Score Error Units
StaticClassLookup.MethodHandles_lookup_lookupClass avgt 30 3.630 ± 0.024 ns/op
StaticClassLookup.AnonymousObject_getClass_enclosingClass avgt 30 282.486 ± 1.980 ns/op
StaticClassLookup.SecurityManager_classContext_1 avgt 30 680.385 ± 21.665 ns/op
StaticClassLookup.Thread_currentThread_stackTrace_1_className avgt 30 11179.460 ± 286.293 ns/op
StaticClassLookup.Throwable_stackTrace_0_className avgt 30 10221.209 ± 176.847 ns/opConclusions
- 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 :(
new Object(){}.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 theSecurityManager
class. You will need some helper class like this:// Helper class
public final class CallerClassGetter extends SecurityManager
{
private static final CallerClassGetter INSTANCE = new CallerClassGetter();
private CallerClassGetter() {} public static Class<?> getCallerClass() {
return INSTANCE.getClassContext()[1];
}
} // Usage example:
class FooBar
{
static final Logger LOGGER = LoggerFactory.getLogger(CallerClassGetter.getCallerClass())
}
- You probably don't ever need to use last two variants based on the
getStackTrace()
from exception or theThread.currentThread()
. Very inefficient and can return only the class name as aString
, not theClass<*>
instance.P.S.
If you want to create a logger instance for static kotlin utils (like me :), you can use this helper:
import org.slf4j.Logger
import org.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")
inline fun loggerFactoryStatic(): Logger
= LoggerFactory.getLogger(MethodHandles.lookup().lookupClass())Usage example:
private val 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) return max
LOGGER.warn("nextDouble: min $min > max $max")
return min
}
return nextDouble() * (max - min) + min
}
总结
Java7中的MethodHandles.lookup().lookupClass(),又快又简洁。
如果条件不允许可以退而求其次用new Object(){}.getClass().getEnclosingClass()
如果用Maven项目,默认是Source和Target都是1.5,需要加上,指定为1.7即可。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
Java中获得当前静态类的类名的更多相关文章
- JAVA中获取当前运行的类名,方法名,行数
JAVA中获取当前运行的类名,方法名,行数 public static String getTraceInfo(){ StringBuffer sb = new StringBuffer(); Sta ...
- Java中获取运行代码的类名、方法名
以下是案例,已运行通过 package com.hdys; /* * 1.获取当前运行代码的类名,方法名,主要是通过java.lang.StackTraceElement类 * * 2. * [1]获 ...
- java中静态方法和静态类的学习
静态内部类可以有静态成员,而非静态类 则不能有静态成员 静态内部类的非静态成员可以访问外部类的静态成员,而不可以访问外部类的非静态成员 非静态方法与对象相关,而静态方法属于类的方法, 总上所述:静态方 ...
- java中的反射,知道类名创建类,还可以设置私有属性的值
刚刚学到了反射,感觉反射的功能好强大,所以想写篇博客记录下自己的学习成果. 利用反射来创建对象. Class c1=Class.forName("test.Person");//通 ...
- Java中的命名规范到底是怎样的
内容摘要:命名规范二,java中的方法名,对象名和字段名的第一个单词的首写字母应该小写,而后面的每个单词的首字母都应该小写 要想将java基础学的十分的牢固就必须将java中的命名规范掌握好了.俗话说 ...
- java中Class对象详解和类名.class, class.forName(), getClass()区别
一直在想.class和.getClass()的区别,思索良久,有点思绪,然后有网上搜了搜,找到了如下的一篇文章,与大家分享. 原来为就是涉及到Java的反射----- Java反射学习 所谓反射,可以 ...
- Java中类名与文件名的关系
1.Java保存的文件名必须与类名一致: 2.如果文件中只有一个类,文件名必须与类名一致: 3.一个Java文件中只能有一个public类: 4.如果文件中不止一个类,文件名必须与public类名一致 ...
- Java中的static关键字解析(转自海子)__为什么main方法必须是static的,因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。
Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...
- JAVA中MESSAGEBOX,静态类直接引用
原文:JAVA中MESSAGEBOX,静态类直接引用 package cisdi.mes.wrm.mcode.serviceImpl; import javax.persistence.Entity; ...
随机推荐
- 洛谷P1803 凌乱的yyy dp
我要日更嘤嘤嘤>_< 原题戳>>https://www.luogu.org/problem/show?pid=1803<<(其实是戳不动的,复制粘贴吧) 题目背景 ...
- sublime插件开发手记
原:http://blog.hickwu.com/sublime插件开发手记 标题: sublime插件开发手记 时间: 2014-01-05 14:58:02 正文: 插件基本结构 基本插件实现 ...
- mac删除python
删除Python框架 sudo rm -rf /Library/Frameworks/Python.framework/Versions/x.x 删除Python本程序 sudo rm -rf &qu ...
- uint8_t / uint16_t / uint32_t /uint64_t数据类型详解
uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型? 在nesc的代码中,你会看到很多你不认识的数据类型,比如uint8_t等.咋一看,好像是个新的数据类型 ...
- android studio 的基本使用和建立一个小项目
https://github.com/allenxieyusheng/Android-Studio
- Pandas——ix 与 loc 与 iloc 与 icol 的区别
来自:https://blog.csdn.net/xw_classmate/article/details/51333646 来自:https://blog.csdn.net/chenKFKevin/ ...
- 《剑指offer》第五十六题(数组中只出现一次的两个数字)
// 面试题56(一):数组中只出现一次的两个数字 // 题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序 // 找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度 ...
- JNI C创建Java字符串数组
创建Java字符串数组 注:jni中没有与String[]对应的数据类型,所以需要创建对象数组,循环添加jstring对象 #include <Sample3.h> #include &l ...
- C++ 实现sqilte创建数据库插入、更新、查询、删除
C/C++ Interface APIs Following are important C/C++ SQLite interface routines, which can suffice your ...
- vue 上传单个图片自定义增加progress改良用户体验
<el-tab-pane label="开发商logo" name="first" style="position: relative;&quo ...