|
Java форум JavaTalks форум программистов
|
|
|
|
| Предыдущая тема :: Следующая тема |
| Автор |
Сообщение |
lagi : 17 Новичок
|
Янв 28, 2012 17:11 |
|
|
Всем привет.
Есть оператор case в котором более 100 условий выбора операции,
| Код: |
switch (type) {
case 0:
return "subscriberServicesIndicator;" + subscriberServicesIndicator(s);
case 1:
return "callIdentificationNumber;" + callIdentificationNumber(s);
|
в условии которое выбралось есть некий выполняемый метод.
И при каждом обращении в класс все эти 100 условий выполняются.
Хотелось бы иметь массив в котором будут храниться эти методы , и при указании ссылки на ячейку в массиве выбирался бы сразу необходимый метод и выполнялся.
Примерно так :
| Код: |
public class JavaApplication1 {
public static void main(String[] args) {
MM[] test = new MM[2];
System.out.println(test[0].hello());
System.out.println(test[1].by());
}
}
class MM {
String hello() {
return "hello";
}
String by() {
return "by";
}
}
|
Но такая конструкция не работает , т.к. при выполнении программы , выпадает ошибка что операция ссылается на пустой(неопределенный) объект(java.lang.NullPointerException)
Помогите найти выход, может как то другим способом решается данная задача.
Заранее большое спасибо. |
|
|
|
 |
rfq : 213 Новичок
|
Янв 28, 2012 17:49 |
|
|
| lagi писал(а): |
Всем привет.
Есть оператор case в котором более 100 условий выбора операции,
| Код: |
switch (type) {
case 0:
return "subscriberServicesIndicator;" + subscriberServicesIndicator(s);
case 1:
return "callIdentificationNumber;" + callIdentificationNumber(s);
|
в условии которое выбралось есть некий выполняемый метод.
И при каждом обращении в класс все эти 100 условий выполняются.
|
Я не вижу здесь 100 условий. Есть 100 вариантов значения type, и 100 вариантов реакции. Выбор реакции по значению type происходит очень быстро: при компиляции создается массив меток перехода, и при исполнении он индексируется. Это как раз то, что вам нужно.
Методы в Java не являются first-class citizens, так что массив методов создать не удасться. Можно, однако, создать 100 классов, в каждом
определить свой метод (с одним и тем же именем, но разным телом), и создать массив объектов разных классов, и уже его индексировать. Но объем текста возрастет в несколько раз. |
|
|
|
 |
shoo : 115 Новичок
|
Янв 28, 2012 18:33 |
|
|
Не совсем понял, что вам нужно, но чтобы пример работал нужно сделать вот так:
| Код: |
class MM {
public static String hello() {
return "hello";
}
public static String by() {
return "by";
}
} |
Либо вот так:
| Код: |
public class JavaApplication1 {
public static void main(String[] args) {
MM[] test = new MM[2];
for (int i = 0; i<test.length; i++) {
test[i] = new MM();
}
System.out.println(test[0].hello());
System.out.println(test[1].by());
}
} |
Почему?
MM[] test = new MM[2];
Вы задаёте массив ссылок класса MM.
То есть, ссылок на объекты null, которым можно присвоить объекты типа MM.
test[0].hello()
То есть, это звучит для компилятора примерно так:
null.hello()
То есть, вам нужно либо создавать экземпляры объектов в массиве, либо назначать static методы, которые могут быть вызваны без создания экземпляра класса. |
|
|
|
 |
rang3r : 13 Новичок
|
Янв 29, 2012 10:29 |
|
|
А как же Java Reflection API, он позволит получить массив методов класса,
Method[] methods = Class#getDeclaredMethods()
и можно работать с массивом, про который имелось в виду в начале |
|
|
|
 |
lagi : 17 Новичок
|
Янв 29, 2012 10:54 |
|
|
| Цитата: |
| Не совсем понял, что вам нужно |
Пишу конвертер для CallDetailRecord CDR (на основе BER1 rules encoding)
Я хочу избежать использования оператора case , в котором приходится проходить всю логическую цепочку, (которая очень длинная , а в цикле это увеличивает время выполнения кода).
В массиве же - я могу обратиться к ячейке указав её номер и сразу получить содержимое (будь то данные или процедура/функция).
У меня есть тип данных который определяется числовым значением
к примеру
| Код: |
public static final short subscriberServicesIndicator = 0;
public static final short callIdentificationNumber = 1;
public static final short recordSequenceNumber = 2;
public static final short typeOfCallingSubscriber = 3; |
и для каждого типа должен выполняться свой метод.
то есть логика такая, в цикле я определяю какой у меня сейчас тип данных:
для какого типа данных мы будем конвертировать его значение , и
в массиве под номером 2 (
| Код: |
| public static final short recordSequenceNumber = 2; |
) для типа данных (recordSequenceNumber ) будет функция "
| Код: |
| recordSequenceNumber(); |
" |
|
|
|
 |
rfq : 213 Новичок
|
Янв 29, 2012 11:52 |
|
|
| rang3r писал(а): |
А как же Java Reflection API, он позволит получить массив методов класса,
Method[] methods = Class#getDeclaredMethods()
и можно работать с массивом, про который имелось в виду в начале |
Можно, но вызов метода через reflection менее эффективен по времени. |
|
|
|
 |
rfq : 213 Новичок
|
Янв 29, 2012 11:58 |
|
|
| lagi писал(а): |
Я хочу избежать использования оператора case , в котором приходится проходить всю логическую цепочку, (которая очень длинная , а в цикле это увеличивает время выполнения кода).
|
Повторяю еще раз: если в case варианты идут последовательно (например, от 0 до 100), то всю логическую цепочку проходить не придется - будет массив меток перехода, проиндексированный значением варианта, и затем переход на нужное предложение. Это самый быстрый способ. При использовании массива методов, будут задействованы дополнительные команды вызова и возврата. |
|
|
|
 |
lagi : 17 Новичок
|
Янв 29, 2012 12:26 |
|
|
| rfq писал(а): |
| lagi писал(а): |
Я хочу избежать использования оператора case , в котором приходится проходить всю логическую цепочку, (которая очень длинная , а в цикле это увеличивает время выполнения кода).
|
Повторяю еще раз: если в case варианты идут последовательно (например, от 0 до 100), то всю логическую цепочку проходить не придется - будет массив меток перехода, проиндексированный значением варианта, и затем переход на нужное предложение. Это самый быстрый способ. При использовании массива методов, будут задействованы дополнительные команды вызова и возврата. |
Хорошо, спасибо останусь на выбранном варианте case, просто думал вдруг есть эффективнее вещь. |
|
|
|
 |
ТокиТори : 1066 Завсегдатай
|
Янв 29, 2012 13:39 |
|
|
| А если написать какой-нибудь интерфейс ExecutableObject, в нем метод execute(). В этом случае для каждого метода будет свой класс, реализующий этот интерфейс. Объекты хранить в Map, вытаскивать по ключу type, а потом вызывать execute(). Пока подводных камней с такой реализацией не вижу. |
|
|
|
 |
lagi : 17 Новичок
|
Янв 29, 2012 14:06 |
|
|
| ТокиТори писал(а): |
| А если написать какой-нибудь интерфейс ExecutableObject, в нем метод execute(). В этом случае для каждого метода будет свой класс, реализующий этот интерфейс. Объекты хранить в Map, вытаскивать по ключу type, а потом вызывать execute(). Пока подводных камней с такой реализацией не вижу. |
Очень интересно, я попробую такой вариант. |
|
|
|
 |
rfq : 213 Новичок
|
Янв 29, 2012 14:53 |
|
|
| ТокиТори писал(а): |
| Объекты хранить в Map, вытаскивать по ключу type, а потом вызывать execute() |
а зачем Map, когда можно в массив? |
|
|
|
 |
lagi : 17 Новичок
|
Янв 29, 2012 15:37 |
|
|
| lagi писал(а): |
| ТокиТори писал(а): |
| А если написать какой-нибудь интерфейс ExecutableObject, в нем метод execute(). В этом случае для каждого метода будет свой класс, реализующий этот интерфейс. Объекты хранить в Map, вытаскивать по ключу type, а потом вызывать execute(). Пока подводных камней с такой реализацией не вижу. |
Очень интересно, я попробую такой вариант. |
У Вас есть возможность более подробно описать Ваш вариант ? Очень хотелось бы понять задумку.
Вот мои первые шаги , но дальше интерфейса дело не идет и как будет выглядеть механизм выбора метода по TYPE_ID, подскажите как быть ?
| Код: |
public class JavaApplication2 {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
}
}
interface interface_test {
String execute();
}
class Hello implements interface_test {
@Override
public String execute() {
return "Hello";
}
}
class By implements interface_test {
@Override
public String execute() {
return "By";
}
}
|
|
|
|
|
 |
ТокиТори : 1066 Завсегдатай
|
Янв 29, 2012 16:27 |
|
|
Теперь, как уже было поправлено выше, инициализируете массив с элементами типа interface_test (подчеркивания в именовании не рекомендуется использовать, имена классов всегда с большой буквы - например, InterfaceTest).
| Код: |
interface_test executableObjects[] = new interface_test[100]
executableObjects[0] = new Hello();
executableObjects[1] = new By();
|
Вроде так. А потом, по мере необходимости, вытаскиваете из массива с нужным индексом объект и вызываете execute() на нем:
| Код: |
executableObjects[0].execute();
|
|
|
|
|
 |
lagi : 17 Новичок
|
Янв 29, 2012 16:44 |
|
|
| ТокиТори писал(а): |
Теперь, как уже было поправлено выше, инициализируете массив с элементами типа interface_test (подчеркивания в именовании не рекомендуется использовать, имена классов всегда с большой буквы - например, InterfaceTest).
| Код: |
interface_test executableObjects[] = new interface_test[100]
executableObjects[0] = new Hello();
executableObjects[1] = new By();
|
Вроде так. А потом, по мере необходимости, вытаскиваете из массива с нужным индексом объект и вызываете execute() на нем:
| Код: |
executableObjects[0].execute();
|
|
Спасибо, все работает. Интересно вот только как это будет по производительности по сравнению с case ? |
|
|
|
 |
rfq : 213 Новичок
|
Янв 29, 2012 17:14 |
|
|
Можно совместить описания классов и массива:
| Код: |
interface_test executableObjects[] = new interface_test[]{
new interface_test() {
@Override
public String execute() {
return "Hello";
}
},
new interface_test() {
@Override
public String execute() {
return "By";
}
}
};
|
|
|
|
|
 |
|
|
|