通常在打印日志的时候需要输出类名,普通类可以用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:

  1. new Object(){}.getClass().getEnclosingClass();
    noted by Tom Hawtin - tackline

  2. getClassContext()[0].getName(); from the SecurityManager
    noted by Christoffer

  3. new Throwable().getStackTrace()[0].getClassName();
    by count ludwig

  4. Thread.currentThread().getStackTrace()[1].getClassName();
    from Keksi

  5. and finally awesome
    MethodHandles.lookup().lookupClass();
    from Rein

I'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/op

Conclusions

  1. Best variant to use, rather clean and monstrously fast.
    Available only since Java 7 and Android API 26!
 MethodHandles.lookup().lookupClass();
  1. 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();
  1. 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 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())
}
  1. 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:

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中获得当前静态类的类名的更多相关文章

  1. JAVA中获取当前运行的类名,方法名,行数

    JAVA中获取当前运行的类名,方法名,行数 public static String getTraceInfo(){ StringBuffer sb = new StringBuffer(); Sta ...

  2. Java中获取运行代码的类名、方法名

    以下是案例,已运行通过 package com.hdys; /* * 1.获取当前运行代码的类名,方法名,主要是通过java.lang.StackTraceElement类 * * 2. * [1]获 ...

  3. java中静态方法和静态类的学习

    静态内部类可以有静态成员,而非静态类 则不能有静态成员 静态内部类的非静态成员可以访问外部类的静态成员,而不可以访问外部类的非静态成员 非静态方法与对象相关,而静态方法属于类的方法, 总上所述:静态方 ...

  4. java中的反射,知道类名创建类,还可以设置私有属性的值

    刚刚学到了反射,感觉反射的功能好强大,所以想写篇博客记录下自己的学习成果. 利用反射来创建对象. Class c1=Class.forName("test.Person");//通 ...

  5. Java中的命名规范到底是怎样的

    内容摘要:命名规范二,java中的方法名,对象名和字段名的第一个单词的首写字母应该小写,而后面的每个单词的首字母都应该小写 要想将java基础学的十分的牢固就必须将java中的命名规范掌握好了.俗话说 ...

  6. java中Class对象详解和类名.class, class.forName(), getClass()区别

    一直在想.class和.getClass()的区别,思索良久,有点思绪,然后有网上搜了搜,找到了如下的一篇文章,与大家分享. 原来为就是涉及到Java的反射----- Java反射学习 所谓反射,可以 ...

  7. Java中类名与文件名的关系

    1.Java保存的文件名必须与类名一致: 2.如果文件中只有一个类,文件名必须与类名一致: 3.一个Java文件中只能有一个public类: 4.如果文件中不止一个类,文件名必须与public类名一致 ...

  8. Java中的static关键字解析(转自海子)__为什么main方法必须是static的,因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  9. JAVA中MESSAGEBOX,静态类直接引用

    原文:JAVA中MESSAGEBOX,静态类直接引用 package cisdi.mes.wrm.mcode.serviceImpl; import javax.persistence.Entity; ...

随机推荐

  1. 【OData】使用Odata获取数据之后再次获取可能得不到最新的数据问题记录

    工作上遇到个问题是关于系统后台数据库更新了某数据后, 前台界面刷新显示的不是最新的数据.但是大约10分后再次刷新就能显示新的数据,或者重启IIS等web server host. 最开始认为可能是因为 ...

  2. Leetcode_Easy_14

    编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". class Solution { public String longestCommonP ...

  3. HDU 1403 Longest Common Substring(最长公共子串)

    http://acm.hdu.edu.cn/showproblem.php?pid=1403 题意:给出两个字符串,求最长公共子串的长度. 思路: 刚开始学后缀数组,确实感觉很难,但是这东西很强大,所 ...

  4. BOM - 浏览器API

     1,javascript   组成部分: 1.ECMAscript(核心标准):    定义了基本的语法,比如:if for 数组 字符串 ... 2.BOM  : 浏览器对象模型(Browser ...

  5. Python安装常见问题:zipimport.ZipImportError: can't decompress data; zlib not available 解决办法

    centos7安装python3.7.2时,报错,解决如下 yum -y install zlib* 参考: https://blog.csdn.net/u014749862/article/deta ...

  6. [转][C++]佛祖保佑,永无bug。C++ BUG解决方案

    // // _oo0oo_ // o8888888o // 88" . "88 // (| -_- |) // 0\ = /0 // ___/`---'\___ // .' \\| ...

  7. JqueryValidate 表单验证插件

    1.适用场景 表单 ( 支持自定义规则 ) 2.相关文章 jQuery Validate 3.实际问题 JqueryValidate表单相同Name不校验问题解决

  8. ubuntu 安装cuda 9.1 pytorch 0.3.0

    毕业再没用配过机器学习的环境了,既亲切又陌生,久违了. 系统 mint18  x64 1安装cuda 按官网提示 选的9.1版  https://developer.nvidia.com/cuda-t ...

  9. Golang atomic

    原子操作函数 分为下面系列函数,其中Xxx可以是Int32/Int64/Uint32/Uint64/Uintptr/Pointer其中一种. 1.SwapXxx系列:交换新旧值: // SwapInt ...

  10. 牛客OI周赛4-提高组 B 最后的晚餐(dinner)

    最后的晚餐(dinner) 思路: 容斥 求 ∑(-1)^i * C(n, i) * 2^i * (2n-i-1)! 这道题卡常数 #pragma GCC optimize(2) #pragma GC ...