【问题标题】:Is it possible to get the type of an uninstantiated variable in Java?是否可以在 Java 中获取未实例化变量的类型?
【发布时间】:2014-11-29 22:58:28
【问题描述】:

是否可以获取在 Java 中声明(但未实例化)的变量的类型? 例如:

public class Foo {

     FooTwo foo2;
     FooTwo foo3;
     FooThree foo4;

     public static void main(String[] args) {
         if (foo2.getClass() == foo3.getClass()) {
             System.out.println("foo2 is the same type as foo3");
         }
         if (foo3.getClass() == foo4.getClass()) {
             System.out.println("foo3 is the same class as foo4");
         }
     }
}

有输出:

foo2 is the same type as foo3

显然getClass() 方法不适用于未实例化的变量,因此该代码不起作用。我假设我正在寻找的信息存储在变量(指针?)中的某个位置以确保类型安全,并且它可能是可访问的。 是否有可能实现这种比较?

原因: 我有一个带有几个声明变量的类。这些变量应该指向存储在另一个类的 ArrayList 中的对象。我正在尝试创建一个将初始化(但未实例化)变量作为参数的方法,扫描数组列表以查找与初始化变量的类型匹配的对象,并将变量设置为对象(使变量指向对象)。

另外:系统的重点是消除类的构造函数中的耦合。对象不能立即实例化,也不能在构造函数中实例化。

【问题讨论】:

  • 这个的用例是什么?什么情况下不知道变量声明的类型?
  • 查看您的术语。 实例化 是适用于类类型并产生实例的东西。变量不是实例。
  • 我将编辑问题并添加一些上下文!你是对的,恐怕我的术语可能完全不符合标准:/我所指的正确术语是什么?
  • 我只称它为空变量(或空字段,如果您想具体说明的话),我认为它是否设置为空或始终为空都没有关系。但是用例肯定会很好,因为我想不出在编译时它不明显的情况
  • 你能添加类 FooTwo 和 FooThree 吗?

标签: java oop pointers object


【解决方案1】:

首先,您需要了解表达式的type 和值的runtime-type 之间的区别。例如,考虑以下代码:

List<String> list = new ArrayList<String>();
System.out.println(list.getClass());

上面的代码打印的是class java.util.ArrayList,而不是java.util.List&lt;java.lang.String&gt;,因为getClass()返回的是list引用的对象的运行时类型,而不是list本身的类型。

因此在未初始化的变量上调用getClass() 是没有意义的,因为它没有返回运行时类型的值。


我正在尝试创建一个方法,它将一个已初始化(但未实例化)的变量作为参数,[...] 并将变量设置为对象(使变量指向对象)。

由于 Java 是一种按值传递的语言,它不会公开修改作为参数传入的变量的方法。例如,考虑这种方法:

public void doNothing(Object obj) {
    obj = "obj";
}

上述方法完全没有任何作用。它有一个局部变量obj,最初包含传入的任何引用,然后改为引用字符串"obj";但是这种更改没有任何效果,因为在那之后实际上没有使用局部变量obj。特别是,这个方法对传入的任何引用都没有任何影响。

你能得到的最接近的是使用反射;如果您的方法采用type Field 的实例,则它既可以检查字段的声明类型,也可以将字段设置为其选择的值。

【讨论】:

  • '它并没有真正公开一种方法来做到这一点',这正是我想要的。所以这就是我所理解的:显然,由于 Java 不是动态类型的,因此声明的变量中有一些信息指示它可以指向哪些对象。即使有这些信息,该语言也没有提供访问它的方法。我理解正确吗?
  • 呃,什么?我想你误解了这句话的意思。我已将答案编辑得更明确。
  • @MikeJava 如果你可以引用一个变量,你必须已经知道它声明的类型,所以你可以直接把它放进去......
  • @LouisWasserman 这是真的!如果这个提议的方法失败,这就是我将依靠的。我想要做的是自动化这个过程。我将有许多子类,所有子类都有不同的声明变量要分配。如果我可以根据声明的变量的类型获得一种方法来为我分析这些,我可以避免复制所有代码。
  • 听起来你应该使用泛型,那么。你不能像那样引用局部变量。
【解决方案2】:

您可以使用反射来做类似的事情。这是一个示例代码 sn-p。但是,如果您更详细地解释您的用例,可能会有更好的方法来解决您的问题。

import java.lang.reflect.Field;

public class Foo {

    static FooTwo foo2;
    static FooTwo foo3;
    static FooThree foo4;

    public static void main(String[] args)  {

        try {
            Field foo2Field = Foo.class.getDeclaredField("foo2");
            Field foo3Field = Foo.class.getDeclaredField("foo3");
            Field foo4Field = Foo.class.getDeclaredField("foo4");

            if (foo2Field.getType().equals(foo2Field.getType())) {
                System.out.println("foo2 is the same type as foo3");
            }
            if (foo3Field.getType().equals(foo4Field.getType())) {
                System.out.println("foo3 is the same class as foo4");
            }

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            // TODO handle this if this can happen
        } catch (SecurityException e) {
            e.printStackTrace();
            // TODO handle this appropriately
        }

    }

}

class FooTwo {

}

class FooThree {

}

【讨论】:

  • 哦哦,这很有趣......而且它可能会起作用。
  • 这成功了!反射非常酷。您的回答帮助我了解了反思的情况并回答了我的问题,但另一个答案,即使我没有马上得到它,也回答了我的问题,更详细地介绍了语言的内部工作原理.所以我会选择那个答案,但谢谢你的时间!
猜你喜欢
  • 2022-08-10
  • 2016-05-21
  • 1970-01-01
  • 2018-05-26
  • 2013-04-17
  • 2016-12-24
  • 2022-01-06
  • 2016-02-18
  • 1970-01-01
相关资源
最近更新 更多