【问题标题】:How can I get an Object's name in java?如何在 java 中获取对象的名称?
【发布时间】:2011-02-23 01:27:36
【问题描述】:

像这样,A a = new A(),我怎样才能得到a的名字?(Get a String "a" from a)?


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

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)。

【问题讨论】:

  • 你能解释一下这在什么情况下会有用吗?假设你有A a = new A();,你期望在你做A b = a;之后返回什么?

标签: java


【解决方案1】:

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

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

A 实例现在的“名称”是什么?是"a"吗?是"b"吗?

那么这个呢?

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

a[1] 上的实例的“名称”是什么?

我的观点是,您无法为适用于各种上下文的通用 Java 对象名称提出有用/可用的定义。障碍问题包括:

  • 名称稳定性:分配对象引用时更改的“名称”没有用。
  • 单一名称:一个对象不应同时具有多个名称。
  • 可实施性:任何命名系统都必须是可实施的,而不会对对象的正常使用造成性能成本。 AFAIK,这是不可能的……至少在我们目前使用的硬件上是这样。

Java 最接近对象名称的是对象的“身份哈希码”值。它不是唯一的,但它具有在当前 JVM 中对象的生命周期内不会改变的属性。 (但即使是身份哈希码也会产生运行时成本……这在某些人看来是 Java 设计错误。)

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


在“对象”实际上是JComponent 的更具体的情况下,不能依赖给定的组件来命名。 (getName() 方法可以返回 null。)但是,如果您愿意,可以遍历任何 JComponent 层次结构并在任何组件上适当地设置名称。

【讨论】:

  • 如果“a”不是一个对象的名字,那你怎么称呼它呢?为对象保留的内存地址的引用?
  • It (a) 是包含对对象的引用的变量的标识符(或“名称”)。它不是对象的“名称”,因为变量中的引用可以更改。对象的“名称”不会因为我将其分配给不同的变量而改变。注意 - 我在这里使用“名称”的方式与撰写原始问题的人相同。
  • 所以,当您说“引用”时,您的意思是内存上的地址,对吧?这意味着,如果我有很多对象,那么每个对象都会有不同的地址。这意味着,我必须为每个对象使用不同的标识符/变量。 '螺柱 a = 新螺柱(“约翰”);螺柱 b = 新螺柱(“迈克尔”);'。对吗?
  • 不一定。 Stud[] studs = new Stud[]{new Stud("John"), new Stud("Fred")};Stud a = new Stud("John"); a = new Stud("Fred");
【解决方案2】:

您可以使用Component.setName() 为 Swing 和 AWT 组件命名。

【讨论】:

  • 也许这是最好的解决方案:)
【解决方案3】:

你不能。

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

【讨论】:

    【解决方案4】:

    你不能,如果你需要这样做,你似乎做错了什么。但是,如果您真的想遵循您概述的逻辑,为什么不执行以下操作:

    将 String 成员添加到 A 并在构造函数中分配它。像这样的:

     A a = new A('a');
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 请注意,getClass 为您提供了 object 的类,而不是变量的类(即,如果您使用 Object x = "hello"x.getClass() 将是 String,而不是 Object)。无法从变量指向的对象中获取局部变量的类 - 就像无法获取变量的名称一样。
      • @sepp2k,我相信您试图在“对象”和“变量”之间做出的区分是非标准的。当试图做出这种区分时,通常会说“运行时类型”与“编译时类型”或“运行时类型”与“声明类型”。我使用“变量”有点通俗/松散地表示变量表示的值。
      • 我不知道它是否是一个标准(尽管我知道我不是第一个制作它的人),但我认为理解一个对象可以被多个指向是很重要的一个变量或根本没有变量,这使得诸如对象名称之类的概念毫无意义。我相信这种区别清楚地表明了这一点,因此是一个有用的区别。
      • @sepp2k,是的,没错,两个不同的变量可能表示同一个底层对象。
      【解决方案6】:

      名称(符号)a 的复制既不方便又有点吵。 在具有宏的语言中,可以定义这一点,以便在源代码程序中自动复制。

      make(A, a);
      

      或 制作A(a)

      【讨论】:

        【解决方案7】:

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

        【讨论】:

          【解决方案8】:

          我遇到了同样的问题,看看那个解决方案...

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

          【讨论】:

          • 给出类名,而不是mb,对象引用名
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-05
          • 2016-09-03
          相关资源
          最近更新 更多