Answers:
为了支持正确的重构(重命名类),则应使用以下任一方法:
 MyClass.class.getName(); // full name with package或(感谢@James Van Huis):
 MyClass.class.getSimpleName(); // class name and no more按照工具包的说明进行操作。不要做这样的事情:
return new Object() { }.getClass().getEnclosingClass();getClass返回运行时类型,因此不能为静态。
                    在Java 7+中,您可以在静态方法/字段中执行此操作:
MethodHandles.lookup().lookupClass()Reflection.getCallerClass()。但是它给出了有关被包含在“ sun”包中的警告。因此,这可能是一个更好的解决方案。
                    Reflection.getCallerClass()东西。对于他的微不足道的操作来说有点复杂,即Optional<Class<?>> myself = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) .walk(s -> s.map(StackWalker.StackFrame::getDeclaringClass) .findFirst());,但是当然,这与事实将更加强大。
                    因此,当我们需要静态获取类对象或类的全名/简单名称而没有显式使用MyClass.class语法时,就会遇到这种情况。
在某些情况下可能非常方便,例如  科特林 高层函数(在这种情况下,kotlin创建了无法从kotlin代码访问的静态Java类)。
科特林 高层函数(在这种情况下,kotlin创建了无法从kotlin代码访问的静态Java类)。
我们有一些不同的变体来获取此信息:
new Object(){}.getClass().getEnclosingClass();
Tom Hawtin 
指出-大头针
getClassContext()[0].getName();从SecurityManager
所指出克里斯托弗
new Throwable().getStackTrace()[0].getClassName();
按路德维希伯爵
Thread.currentThread().getStackTrace()[1].getClassName();
来自Keksi
最后
MethodHandles.lookup().lookupClass();
来自Rein
我准备了一个 m 所有变体的基准,结果是:
# 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 MethodHandles.lookup().lookupClass(); new Object(){}.getClass().getEnclosingClass();如果您在许多地方都需要它,又不希望由于大量匿名类而使您的字节码膨胀,那SecurityManager就是您的朋友(第三好的选择)。
但是您不能随便打电话getClassContext()-它在SecurityManager课程中受到保护。您将需要一些这样的帮助器类:
 // 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())
 }getStackTrace()from异常或的最后两个变体Thread.currentThread()。非常低效,只能将类名作为String,而不返回Class<*>实例。如果您想为静态kotlin utils(如我:)创建记录器实例,则可以使用以下帮助器:
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())用法示例:
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
}该指令可以正常工作:
Thread.currentThread().getStackTrace()[1].getClassName();Thread.getStackTrace()您会发现它除了return (new Exception()).getStackTrace();在上被调用外没有任何其他作用currentThread()。因此,@ count ludwig的解决方案是实现相同目标的更直接方法。
                    通过使用JNI,您可以做一些非常可爱的事情:
MyObject.java:
public class MyObject
{
    static
    {
        System.loadLibrary( "classname" );
    }
    public static native String getClassName();
    public static void main( String[] args )
    {
        System.out.println( getClassName() );
    }
}然后:
javac MyObject.java
javah -jni MyObject然后:
MyObject.c:
#include "MyObject.h"
JNIEXPORT jstring JNICALL Java_MyObject_getClassName( JNIEnv *env, jclass cls )
{
    jclass javaLangClass = (*env)->FindClass( env, "java/lang/Class" );
    jmethodID getName = (*env)->GetMethodID( env, javaLangClass, "getName",
        "()Ljava/lang/String;" );
    return (*env)->CallObjectMethod( env, cls, getName );
}然后将C编译到一个名为的共享库中libclassname.so并运行Java!
*咯咯笑
Java_MyObject_getClassName已嵌入名称。解决方法是使用JNI RegisterNatives。当然,您必须将其与JNI配合使用FindClass(env, 'com/example/MyObject'),所以那里也没有胜利。
                    private static final String TAG = "MyClass"或private static final String TAG = MyClass.class.getSimpleName();第二种方法更适合使用IDE进行全局类重命名。
                    我用它来初始化类顶部的Log4j Logger(或注释)。
PRO:Throwable已经加载,您可以通过不使用“ IO重载” SecurityManager来节省资源。
缺点:关于这是否适用于所有JVM的一些问题。
// 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()); 滥用SecurityManager
System.getSecurityManager().getClassContext()[0].getName();或者,如果未设置,请使用扩展它的内部类(下面的示例从Real的HowTo卑鄙地复制了):
public static class CurrentClassGetter extends SecurityManager {
    public String getClassName() {
        return getClassContext()[1].getName(); 
    }
}逐字使用呼叫方的类,例如 MyClass.class.getName()实际完成此工作,但是如果将此代码传播到需要该类名的多个类/子类中,则很容易复制/粘贴错误。
还有汤姆·霍顿的食谱实际上还不错,只需要以正确的方式烹饪即可:)
如果您有一个带有静态方法的基类,可以从子类中调用该静态方法,并且此静态方法需要知道实际的调用者的类,则可以通过以下方式实现:
class BaseClass {
  static sharedStaticMethod (String callerClassName, Object... otherArgs) {
    useCallerClassNameAsYouWish (callerClassName);
    // and direct use of 'new Object() { }.getClass().getEnclosingClass().getName()'
    // instead of 'callerClassName' is not going to help here,
    // as it returns "BaseClass"
  }
}
class SubClass1 extends BaseClass {
  static someSubclassStaticMethod () {
    // this call of the shared method is prone to copy/paste errors
    sharedStaticMethod (SubClass1.class.getName(),
                        other_arguments);
    // and this call is safe to copy/paste
    sharedStaticMethod (new Object() { }.getClass().getEnclosingClass().getName(),
                        other_arguments);
  }
}一种重构安全,剪切和粘贴安全的解决方案,避免了以下临时类的定义。
编写一个静态方法来恢复类名,并小心地将类名包含在方法名中:
private static String getMyClassName(){
  return MyClass.class.getName();
}然后以您的静态方法调用它:
public static void myMethod(){
  Tracer.debug(getMyClassName(), "message");
}通过避免使用字符串来提供重构安全性,并允许剪切和粘贴安全性,因为如果剪切和粘贴调用方方法,您将在目标“ MyClass2”类中找不到getMyClassName(),因此您将不得不重新定义和更新它。
由于这个问题,是类似“ this.class”而不是“ ClassName.class”的?被标记为与此重复(这是有争议的,因为该问题是关于类而不是类名的),我在这里发布答案:
class MyService {
    private static Class thisClass = MyService.class;
    // or:
    //private static Class thisClass = new Object() { }.getClass().getEnclosingClass();
    ...
    static void startService(Context context) {
        Intent i = new Intent(context, thisClass);
        context.startService(i);
    }
}定义thisClass为私有很重要,因为:
1)不能继承:派生类必须定义自己的类,thisClass否则会产生错误消息
2)其他类的引用应采用ClassName.class而不是ClassName.thisClass。
有了thisClass定义,访问类的名称变为:
thisClass.getName()我需要多个类的静态方法中的类名,因此我使用以下方法实现了JavaUtil类:
public static String getClassName() {
    String className = Thread.currentThread().getStackTrace()[2].getClassName();
    int lastIndex = className.lastIndexOf('.');
    return className.substring(lastIndex + 1);
}希望对您有所帮助!
我在static和non static场景中都使用了这两种方法:
主班:
//For non static approach
public AndroidLogger(Object classObject) {
    mClassName = classObject.getClass().getSimpleName();
}
//For static approach
public AndroidLogger(String className) {
    mClassName = className;
}如何提供类别名称:
非静态方式:
private AndroidLogger mLogger = new AndroidLogger(this);静态方式:
private static AndroidLogger mLogger = new AndroidLogger(Myclass.class.getSimpleName());
try{ throw new RuntimeEsception();} catch(RuntimeEcxeption e){return e.getstackTrace()[1].getClassName();}