Java - 获取当前类名?

363

我想做的就是获取当前类名,但Java会在我的类名末尾添加一个无用的非常规$1。如何摆脱它并仅返回实际的类名?

String className = this.getClass().getName();

2
你是在哪里调用这个函数的?是在匿名内部类中吗?能否添加更多代码以显示类的定义细节和调用此行的位置? - plainjimbo
9
所以,你想要的只是 String className = getClass().getName().substring(0, getClass().getName().indexOf("$")) - josh.trow
12
如果你得到了 $1,那是因为这个类的名字是 $1。如果你期望得到其他内容,请在正确的类中使用 this 而不是错误的类。 - ceving
12个回答

333

尝试一下,

String className = this.getClass().getSimpleName();
这将只在非静态方法中起作用。

2
实际上,这样做行不通。这个问题表明他有一个匿名内部类,在这种情况下,getSimpleName()返回"" - vikingsteve
78
尽管这并没有回答问题,但是这篇Stack Overflow文章在谷歌上“获取Java类名”搜索结果中排名靠前,因此对社区仍然有帮助。 - EdgeCaseBerg
13
它将返回不带包命名空间的名称。很好! - Oleg Abrazhaev
获取静态方法中的类名,请参见此答案。 - not2savvy

292

“$1”不是“无用的废话”。如果你的类是匿名的,那么会附加一个数字。

如果你不想要类本身,而是其声明类,则可以使用getEnclosingClass()。例如:

Class<?> enclosingClass = getClass().getEnclosingClass();
if (enclosingClass != null) {
  System.out.println(enclosingClass.getName());
} else {
  System.out.println(getClass().getName());
}

你可以将它放在一些静态实用方法中。

但请注意,这不是当前类名。匿名类是与其封闭类不同的类。内部类的情况类似。


5
如果封装类也是匿名内部类怎么办?你需要递归地获取封装类,直到它返回“null”,然后使用最后一个非“null”的类。 - Garret Wilson

35

尝试使用以下代码:this.getClass().getCanonicalName()this.getClass().getSimpleName()。如果这是一个匿名类,则使用this.getClass().getSuperclass().getName()


实际上,它确实可以。具体取决于情况。如果您正在尝试使用匿名类实现抽象类的名称,则可以使用此方法。 - MirroredFate
对于他的情况(匿名类),简单名称为空,规范名称为null,超类是Object。 - Bozho
是的,是的,不是。我的前两个只是猜测,然而第三个是正确的。匿名类是实现它的类的子类。这就是它们能够工作的原因。因此,超类是抽象类。 - MirroredFate
奇怪的是,超类不是你要继承的类吗?Handler并没有从我的类中继承,它只是一个成员。 - aryaxt
嗯...我已经测试过了,我得到的匿名类的超类是抽象类。我会重新检查我的逻辑...但是既然我得到了有意义的结果,我不认为是我犯了错误... - MirroredFate
啊,你可能在使用“this”,而我正在使用实际的匿名类变量(无论它是什么)。当你说“this”时,你指的是它被执行的对象,而不是匿名类本身。 - MirroredFate

16
您可以使用this.getClass().getSimpleName(),如下所示:
import java.lang.reflect.Field;

public class Test {

    int x;
    int y;  

    public String getClassName() {

        String className = this.getClass().getSimpleName(); 
        System.out.println("Name:" + className);
        return className;
    }

    public Field[] getAttributes() {

        Field[] attributes = this.getClass().getDeclaredFields();   
        for(int i = 0; i < attributes.length; i++) {
            System.out.println("Declared Fields" + attributes[i]);    
        }

        return attributes;
    }

    public static void main(String args[]) {

        Test t = new Test();
        t.getClassName();
        t.getAttributes();
    }
}

4
两者的组合,同时输出一个方法名称:
Class thisClass = new Object(){}.getClass();
String className = thisClass.getEnclosingClass().getSimpleName();
String methodName = thisClass.getEnclosingMethod().getName();
Log.d("app", className + ":" + methodName);

3
这个回答有些晚了,但我认为在匿名处理程序类的上下文中还有另一种方法可以做到这一点。
假设:
class A {
    void foo() {
        obj.addHandler(new Handler() {
            void bar() {
                String className=A.this.getClass().getName();
                // ...
            }
        });
    }
}

它将实现相同的结果。此外,由于每个类都是在编译时定义的,因此实际上非常方便,因此没有破坏动态性。

如果类真的是嵌套的,即A实际上被B所包含,则可以轻松知道B的类:

B.this.getClass().getName()

3
这里有一个Android变体,但同样的原理也可以在普通Java中使用。
private static final String TAG = YourClass.class.getSimpleName();
private static final String TAG = YourClass.class.getName();

2
在您的例子中,this 可能是指一个匿名类实例。Java 会通过在封闭类名称后附加 $number 来为这些类命名。

2
非匿名内部类被命名为Outer$Inner。这将是一个匿名类。 - Duncan McGregor

1

我猜这是发生在匿名类中。当你创建一个匿名类时,实际上你创建了一个继承了你所得到的类的类。

获取你想要的名称的“干净”方法是:

如果你的类是一个匿名内部类,getSuperClass() 应该会给你它所创建的类。如果你从一个接口创建它,那么你就有点麻烦了,因为你最好能做的只是使用 getInterfaces(),但这可能会给你多个接口。

“hacky”的方法是使用 getClassName() 获取名称,并使用正则表达式删除 $1


0
在我的情况下,我使用这个Java类:
private String getCurrentProcessName() {
    String processName = "";
    int pid = android.os.Process.myPid();
    
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
        if (processInfo.pid == pid) {
            processName = processInfo.processName;
            break;
        }
    }
    
    return processName;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接