Обычная версия
Java форум JavaTalks
форум программистов

Поиск   Пользователи   Группы   Регистрация 
 Профиль   Личные сообщения 

 Вход 

Хранение методов в массиве
Список форумов
 ->  Коллекции (Java Collection Framework)


На страницу 1, 2  След. 
Начать новую тему 
Предыдущая тема :: Следующая тема  
Автор Сообщение
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()
и можно работать с массивом, про который имелось в виду в начале
К началу Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
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";
   }
   }
};
К началу Посмотреть профиль Отправить личное сообщение
 
Начать новую тему  Ответить на тему
Страница 1 из 2
На страницу 1, 2  След.
Список форумов
 -> Коллекции (Java Collection Framework)


 
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Java and all Java-related trademarks and logos are trademarks or registered trademarks of Oracle Corporation in the United States and other countries.
Это сайт не относится к фирме Oracle Corporation и не поддерживается ею.

© 2006-2010 www.javatalks.ru: форум java программистов
Используется скрипт phpBB © 2001, 2010 phpBB Group

Хостинг от bizname.ru