Java中eval()解析器和2d数组的实现



我真的被两个Java相关的问题卡住了。一个简单,一个更难。

关于创建一个2D数组,我初始化一个表,像这样:

private String [][] table_of_classifiers = null;

,然后,在函数中,我像这样填充它的内容:

        String [][] table_of_classifiers = {
            {"x1","x","x","x","x"},
            {"x2","x","x","x","x"},
            {"x3","x","x","x","x"},
            {"x4","x","x","x","x"},
            {"x5","x","x","x","x"},
            {"x6","x","x","x","x"},
        };

但是,正如您可以猜到的那样,第二个表(在本地)覆盖了第一个表,这当然不是我想做的。我做错了什么?注意,表的维度从一开始就不知道。

关于创建一个2D数组,我初始化一个表,像这样:

private String [][] table_of_classifiers = null;

没有。这是一个变量的声明和初始化,该可以指向的"2d数组"、"表",或者更确切地说,指向string的"数组的数组"。

除非您处理变量可以/将为null的事实,否则将其初始化为null通常是一个坏主意,因为您需要做额外的工作来检查是否为null。例子:

String[][] a;
// ...
String b = a[0][0];

这不会编译,除非a同时没有初始化。这是一件好事,因为您可以避免潜在的错误。

String[][] a = null;
// ...
String b = a[0][0];

然而,这将编译,如果你忘记实际分配变量一个真正的数组,程序将"崩溃"与一个"空指针异常",或者你需要添加额外的代码/工作来检查null

我这样填充它的内容:

String [][] table_of_classifiers = {
  {"x1","x","x","x","x"},
  {"x2","x","x","x","x"},
  {"x3","x","x","x","x"},
  {"x4","x","x","x","x"},
  {"x5","x","x","x","x"},
  {"x6","x","x","x","x"},
};

你没有在这里"填充"任何东西。要填充某个东西,它必须先存在,但你还没有创造任何东西。

在这里,你声明了第二个同名的变量,这只有在你处于与第一个变量不同的作用域时才有可能,在这种情况下,你"隐藏"("遮蔽")了原来的变量,如果它最初可以从这个新作用域访问。

但是您可以猜到第二个表(在本地)覆盖了第一个表第一,这当然不是我想做的。我做错了什么?

哪个"第一个"表?直到现在还没有第一个表,只有第一个变量。其他人已经向您展示了如何将"表"分配给原始变量,即不使用行开头的"声明"String[][]

否则你不可能说出你"做错了什么",因为你还没有真正解释你想做什么。

注意,表的维数从一开始就不知道。

不是吗?你如何/为什么要使用数组字面量呢?字面值数组用于创建具有固定"预填充"的固定大小的数组。

"开始"到底是什么意思?在编程时(在编译时)或程序启动时(在运行时)不知道大小吗?

如果你在运行时得到数组的大小,你可以用new:

创建一个普通的数组。
int a = ...; 
int b = ...; // Get the sizes from somewhere, e.g, user input 
String[][] table_of_classifiers = new String[a][b];
// Now you have an "empty" table

如果大小在运行时"改变",那么-取决于你实际试图做什么-那么数组是错误的工具,你应该使用List实现,如ArrayList代替。


关于"eval",正如其他人所说,Java是一种编译语言,因此"eval"基本上是不可能的。这是"反射"或使用Class类型来实现您所暗示的,但您确实需要更广泛地解释您正在尝试实现的目标,然后它可能会在这里帮助您。

然而,反射和CLass类型是一个复杂的问题,考虑到您显然正在与最基本的Java概念作斗争,在您能够做您想做的事情之前,您还有很长的路要走。

Just do:

class Foo {
    private String [][] table_of_classifiers = null;
    void bar() {
        table_of_classifiers = new String[][] {
                    {"x1","x","x","x","x"},
                    {"x2","x","x","x","x"},
                    {"x3","x","x","x","x"},
                    {"x4","x","x","x","x"},
                    {"x5","x","x","x","x"},
                    {"x6","x","x","x","x"},
        };
    }
}

Java没有eval(因为它是一种编译语言),但是它有反射。然而,无论你想做什么,这几乎肯定不是最好的方法。

关于你的第一个问题:分配给table_of_classifiers而不重新声明它,写:

        table_of_classifiers = new String[][] {
            {"x1","x","x","x","x"},
            {"x2","x","x","x","x"},
            {"x3","x","x","x","x"},
            {"x4","x","x","x","x"},
            {"x5","x","x","x","x"},
            {"x6","x","x","x","x"},
        };

关于eval…问题是运行时没有作用域局部变量的名称,尽管它可以获得实例变量的名称,但它必须在对象的上下文中这样做。解决这些问题是有可能的,但这不是微不足道的,需要做出重大妥协。我认为你必须彻底理解作用域是如何工作的,以及反射是如何工作的你开始弄清楚eval将支持哪些特性之前,因为否则你只会对你给它的所有要求感到失望,这些要求最终被证明是不可能的。

最新更新