如何从该类的静态方法中获取该类的名称。例如

public class MyClass {
    public static String getClassName() {
        String name = ????; // what goes here so the string "MyClass" is returned
        return name;
    }
}

为了把它放在上下文中,我实际上想在异常中返回类名作为消息的一部分。


当前回答

按照@toolkit说的去做。不要做这样的事情:

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

(编辑:或者如果你使用的Java版本是在这个答案最初写出来之后才出现的,使用@Rein的答案。)

其他回答

像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);
  }
}

我在静态和非静态场景中都使用了这两种方法:

主要课程:

//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());

通过使用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的共享库中。然后运行java!

*笑

这条指令工作得很好:

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

一种重构安全、剪切和粘贴安全的解决方案,避免了下面定义的临时类。

写一个恢复类名的静态方法,注意在方法名中包含类名:

private static String getMyClassName(){
  return MyClass.class.getName();
}

然后在你的静态方法中召回它:

public static void myMethod(){
  Tracer.debug(getMyClassName(), "message");
}

重构安全性是通过避免使用字符串来实现的,剪切和粘贴安全性是被授予的,因为如果你剪切和粘贴调用者方法,你将在目标“MyClass2”类中找不到getMyClassName(),所以你将被迫重新定义和更新它。