通常在打印日志的时候需要输出类名,普通类可以用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. springboot搭建环境整合jsp页面整合mybatis

    1.pom文件依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www ...

  2. Gym 100247B Similar Strings(哈希+思维)

    https://vjudge.net/problem/Gym-100247B 题意: 如果两个字符串通过映射后是一样的,则说明这两个字符串是相似的,现在给出n个字符串,计算出有多少组字符串是相似的. ...

  3. 阿里巴巴数据库连接池 druid配置详解

    一.背景 java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池.数据库连接池有很多选择,c3p.dhcp.proxool等,druid作为一名后起之秀,凭借其出色 ...

  4. 新加坡金融科技节 | 蚂蚁金服CTO程立:面向全球开放,与合作伙伴共赢

    小蚂蚁说: 11月13日,在新加坡金融科技节上,蚂蚁金服CTO程立分别从TechFin.BASIC战略.SOFAStack全栈分布式体系以及全面开放等方面讲述蚂蚁金融科技. TechFin是一种“倒立 ...

  5. 如果调用.net core Web API不能发送PUT/DELETE请求怎么办?

    通过阅读大佬的文章 http://www.cnblogs.com/artech/p/x-http-method-override.html想到的 通过注册中间件来解决这个问题 public void ...

  6. Qt5_选择文件对话框

    1. 类似如下代码: QString fileName = QFileDialog::getOpenFileName( this, tr("Open File"), NULL,// ...

  7. 基于Arcface 免费离线人脸识别 2.0 Demo C#

    本来打算做个C#版demo,但没用成功.使用虹软最新人脸识别技术开发完成 过程如下: 1. 传入一张单人脸照片: 2.调用检测人脸函数ASFDetectFaces,成功返回人脸信息的指针: 3.使用 ...

  8. 学习笔记31—endnote设置

    修改文献引用设置: JournalArticle: Author. (Year). Title. [Translated Title]. [Reviewed Item]. Journal|, Volu ...

  9. MYSQL去除"/r/n"

    #去除回车符号/r/n UPDATE t_week_power_line_loss SET `line_loss_rate` = REPLACE( REPLACE( `line_loss_rate` ...

  10. Unity---资源管理中不同资源的路径获取方式

    1.首先需要先了解两个知识点: Unity内置的文件路径获取方式.windows的Directory.GetFiles文件获取方式:   1>Unity内置的文件路径获取方式,一下是官方解释:h ...