Реализация парсера eval () и 2d массива в Java - PullRequest
1 голос
/ 17 декабря 2011

Я застрял на двух проблемах, связанных с Java.Один простой и еще один сложный.

Что касается создания двумерного массива, я инициализирую таблицу следующим образом:

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"},
        };

Но, как вы можете догадаться, вторая таблица перезаписывает (локально) первую, что, конечно, я не хочу делать.Что я делаю не так?Обратите внимание, что размер таблицы неизвестен с самого начала.

Ответы [ 3 ]

1 голос
/ 17 декабря 2011

Что касается создания двумерного массива, я инициализирую таблицу следующим образом:

private String [][] table_of_classifiers = null;

Не совсем.Это объявление и инициализация переменной , которая может указывать на «2d массив», «таблицу» или, точнее, «массив массивов» строк.

Если вы не работаете с тем фактом, что переменная может / будет иметь значение 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, вам предстоит пройти долгий путь, пока вы не сможете делать то, что хотите.

0 голосов
/ 17 декабря 2011

По поводу вашей первой проблемы: чтобы присвоить 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, потому что в противном случае вы просто будете разочарованы всеми требованиями, которые вы предъявляете в этот ход. быть невозможным.

0 голосов
/ 17 декабря 2011

Просто сделай:

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 (потому что это скомпилированный язык), но у него есть отражение . Это почти наверняка не лучший подход к тому, что вы хотите сделать.

...