如何在Java中获取对象的名称?

12

像这样,A a = new A(),我该如何获取a的名称?(从a中获取一个字符串“a”)?


有一个JPanel包含一些JTextField,一个映射包含所有JTextField的名称(变量的名称)。我想将映射的值设置为JTextField的文本。

public void mapToJPanel(Map map, JPanel panel) {
    Component[] compArr = panel.getComponents();
    for (Component comp : compArr) {
        if (comp.getClass().getSimpleName().equals("JTextField")) {
            JTextField textField = (JTextField) comp;
            textField.setText(map.get(textField.getName()).toString());//getName() method
        }
    }
}

通过getName()方法,我得到了null -_- 我知道getName()方法不是用来获取变量名的。 我正在使用netbeans进行Java Swing可视化开发,所以我无法重写组件(如JTextField)。


5
你能解释一下这种情况有什么用处吗?假设你有A a = new A();,在执行A b = a;后,你会期望返回什么? - akf
8个回答

17

你不能,因为一个对象没有名字。例如考虑以下代码:

A a = new A();
A b = a;

现在,A实例的“name”是什么?它是 "a" 吗?还是 "b"

那么这个呢?

A[] a = new A[] { new A(), new A()};
a[0] = a[1];

a[1] 实例中,“name”是什么?

我的观点是,你无法提出一种有用/可用的通用Java对象名称定义,适用于广泛的上下文。阻碍问题包括:

  • 名称稳定性:当一个对象的引用被分配时发生改变的“名称”是没有用的。
  • 单一名称:一个对象不应同时具有多个名称。
  • 可实现性:任何命名系统都必须在不对对象的正常使用施加性能代价的情况下可实现。据我所知,这是不可能的......至少在我们当前使用的硬件上是不可能的。

Java 最接近的给对象起名字的方法是对象的“标识哈希码”值。它不是唯一的,但它具有这样的属性,即它在当前JVM中对象的生命周期内不会发生变化。(但即使是identity hashcode也需要运行时成本...在某些人看来这是Java设计的错误。)

对于给对象命名的明智做法是(正如其他人所说)向相关类添加“名称”字段(或使用现有字段)并根据需要自行管理名称。


在更具体的情况下,“对象”实际上是JComponent,不能保证给定组件具有名称。(getName()方法可能返回null。)但是,如果你愿意的话,你可以遍历任何JComponent层次结构,并根据需要在任何组件上设置名称。


如果“a”不是一个对象的名称,那么你怎么调用它呢?是指内存中为对象保留的地址吗? - sotirios
1
它(a)是一个变量的标识符(或者"名称"),它包含了对对象的引用。它不是一个对象的"名称",因为变量中的引用可以被改变。如果我将其分配给另一个变量,那么对象的"名称"不会改变。请注意 - 我在这里使用"名称"的方式与原始问题的作者相同。 - Stephen C
所以,当你说“引用”时,你指的是内存中的地址,对吗?这意味着,如果我有许多对象,那么每个对象都会有一个不同的地址。这意味着,我必须为每个对象使用不同的标识符/变量。´Stud a = new Stud("John"); Stud b = new Stud("Michael");´。是这样吗? - sotirios
1
不一定。Stud[] studs = new Stud[]{new Stud("John"), new Stud("Fred")}; 或者 Stud a = new Stud("John"); a = new Stud("Fred"); - Stephen C

6

不行。

如果你使用调试符号编译,那么.class文件将包含一个变量名表(这是调试器将变量映射回你的源代码的方式),但不能保证一定存在,并且它在运行时不会被暴露出来。


6

1
也许这是最好的解决方案 :) - Keating

1

如果你需要这样做,那么似乎你正在做一些错误的事情,因此你不能这样做。然而,如果你真的想追求你所概述的逻辑,为什么不按照以下步骤进行:

在 A 中添加一个字符串成员,并在构造函数中进行赋值。就像这样:

 A a = new A('a');

0

虽然您可以通过调用.getClass().getCanonicalName()或.getClass().getSimpleName()(取决于您是否需要完全限定名称)轻松获取变量类的名称,但是获取变量名称并不那么容易。Java字节码不需要保留局部变量的名称(这些变量使用堆栈上的push/pop操作表示); 但是,Java字节码可能包含注释中的原始名称。因此,您可以尝试从.jar文件中读取.class文件,并尝试从.class文件中提取变量名称,假设编译器已将它们作为注释包含在内。至于成员变量(即字段),您可以使用反射来获取类的字段名称。


请注意,getClass方法返回的是对象的类,而不是变量的类(例如,如果您执行Object x = "hello",则x.getClass()将是String,而不是Object)。无法从变量所指向的对象中获取局部变量的类 - 就像无法获取变量的名称一样。 - sepp2k
@sepp2k,你试图区分“对象”和“变量”的区别是非标准的。当试图做出这种区分时,通常会讲到“运行时类型”与“编译时类型”,或者是“运行时类型”与“声明类型”。我在有些随意的情况下使用“变量”一词,指代变量所表示的值。 - Michael Aaron Safyan
我不确定它是否是标准(虽然我知道我不是第一个这样做的人),但我认为重要的是要理解一个对象可以被多个变量指向,也可以没有任何变量指向,这使得像对象名称这样的概念毫无意义。我相信这种区别能够清晰地表达出来,因此是有用的。 - sepp2k
@sepp2k,是的,这是真的,两个不同的变量可能表示相同的基础对象。 - Michael Aaron Safyan

0

您可以在对象的类中始终创建名称变量,并将该变量与其他变量一起使用,以传递有关此对象的信息。


0

名称(符号)a的复制是有点不方便和嘈杂的。

在具有宏的语言中,可以定义这样一个功能,使得源代码程序中的复制自动完成。

make(A, a);

或者 makeA(a)


-1

我曾经遇到过同样的问题,看看这个解决方案...

    DocumentoMB mb = new DocumentoMB();
    System.out.println(mb.getClass().getSimpleName());

这给出了类名,而不是 mb,对象引用名称。 - OneCricketeer

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