【问题标题】:Reference a variable that cannot be resolved at compile-time. (java)引用在编译时无法解析的变量。 (爪哇)
【发布时间】:2018-03-19 04:17:54
【问题描述】:

我正在创建一个程序,我在运行时使用例如:

String hero1builder = "index.";
System.out.println("Enter hero 1:");
hero1 = scanner.nextLine();
hero1builder += hero1;
hero1cls = Class.forName(hero1builder);
System.out.println("Hero 1 found");

所有这些代码都在 try/catch 中并按预期工作。 当我想引用我引用的类中的变量时,我的挑战就来了。

在编译时,java 注意到我想在这里引用的变量还不能被解析并且它不会编译。我怎样才能绕过这个,所以我可以引用类内部的变量?

String[] hero1list = hero1cls.counterList;

我尝试了许多方法来引用变量 counterList,但没有一个奏效。 hero1cls 保持动态很重要,否则我的程序将无法运行。

(在这个例子中, index 是包,所以 index.Abaddon.counterList 是我想要引用的。如果我这样明确地写出来,这将非常有效。)(PS 2:这不是范围问题. counterList 是这个程序中唯一会抛出错误的东西,并且 hero1cls.getField() 等方法有效。)

这是我引用的类的示例:

package index;

public class Abaddon {
    public static String[] counterList = {"Axe",
                   "AncientApparition",
                   "Doom",
                   "Lina",
                   "Lion",
                   "OutworldDevourer",
                   "ShadowDemon",
                   "Slark",
                   "Undying"
    };
}

【问题讨论】:

  • 以这种方式创建的类需要implement 一个普通的interface。查找这些关键词以及如何对其进行编码。 (另外,classForName() 几乎可以肯定是错误的方法。只要做一个普通的类,它会更容易。)

标签: java class dynamic compiler-errors


【解决方案1】:

您应该利用 Java 反射方法,在这种特殊情况下使用 Class#getField 方法。 代码如下:

String hero1builder = "index.";
System.out.println("Enter hero 1:");
hero1 = scanner.nextLine();
hero1builder += hero1;
hero1cls = Class.forName(hero1builder);
System.out.println("Hero 1 found");
Field counterListField = hero1cls.getField("counterList");
String[] counterList = (String[])counterListField.get(null);
System.out.println(Arrays.toString(counterList);

请注意,counterList.get(null) 之所以有效,只是因为counterList 是一个静态字段,否则您应该向 Abaddon 类传递一个实例。

【讨论】:

  • 这工作得很好,但唯一的问题是 get(null);它说它不能在数组类型字符串上调用 get null。另外,getField 函数返回的是对象类型,而不是字段类型,所以我不得不将其更改为对象。
  • 我不确定我是否理解您在说什么。我已经在你的课堂上测试了这段代码,它可以工作。您使用的是什么版本的 Java?
  • 我认为我的回答解决了这个问题,如果它没有让我们看看我是否可以解决它。你想做什么/想知道更多?
  • 我试过在 jre 1.8 和 1.5 中运行它。两者都抛出 Field cannot be resolved to a type and get(null) cannot be invoked on array type String.
  • 你是对的,我错误地将 Field 和 String[] 变量命名为同名!现在我已经纠正了它,它现在应该可以工作了
【解决方案2】:

如果你想摆脱get(null)并处理非静态成员,你可以通过调用clazz.newInstance()来创建Adaddon的实例,如下所示,

    String className = "index.Abaddon";
    Class<?> clazz = Class.forName(className);
    Field field = clazz.getDeclaredField("counterList");
    if (field.getType().isArray()) {
        final String[] arr = (String[]) field.get(clazz.newInstance());
        System.out.println(Arrays.toString(arr));
    }

【讨论】:

  • 这样效果更好,但我仍然收到“字段”无法解析为类型的错误。我需要为此导入一个库吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-15
  • 2012-11-20
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
  • 2022-07-06
相关资源
最近更新 更多