2012-05-18 1 views
4

Что я хочу сделать, так это легко передать реальный объект метода другому методу. Это значит, что я могу создать общую функцию Joiner, которая объединяется в заданный метод списка объектов без опасности просто передать строку, представляющую этот метод. Возможно ли это в Java, так что я могу иметь синтаксис, как:Как вы можете передать фактический метод в качестве параметра другому методу в Java?

joinOnMethod(String, Collections<T>, Method) e.g. 
joinOnMethod(", ", someList, T.getName()) 

Где T.getName() передает метод GetName() в называться по каждому объекту в списке вместо прохождения в тип возвращаемого значения самого метода.

Надеется, что это достаточно ясно для моих потребностей,

Алексей Синего.

ответ

6

Нет прямой поддержки функций в Java. Два варианта:

  • Пасс во имя метода, и использование отражения, чтобы получить у него
  • Создание типа с одним членом, например:

    public interface Function<In, Out> { 
        Out apply(In input); 
    } 
    

    Затем вы можете использовать анонимный внутренний класс, как это:

    joinOnMethod(", ", someList, new Function<T, String>() { 
           @Override public String apply(T input) { 
            return input.getName(); 
           } 
          }); 
    

    конечно, вы можете извлечь эту функцию в качестве переменной:

    private static Function<T, String> NAME_EXTRACTOR = 
        new Function<T, String>() { 
         @Override public String apply(T input) { 
          return input.getName(); 
         } 
        }; 
    
    ... 
    
    joinOnMethod(", ", someList, NAME_EXTRACTOR); 
    
+5

Drive-by downvoter: оставьте комментарий, объяснив, что вы считаете неправильным с этим ответом. Я уверен, что Джон улучшит свой ответ, если у вас есть верный момент. Но, скорее всего, вам помогут объяснения ваших заблуждений. –

+0

Отличный ответ Джон (вы, кажется, отвечаете на все мои вопросы Java ^. ^). Это было бы здорово, но я бы в конечном итоге создал тысячи из них для каждого метода, так как база кода огромна. Надеюсь, Java в некоторой степени поддержит это в какой-то момент :) –

+0

@AlexeiBlue: у Java 8 будет больше поддержки для этого, но я подозреваю, что вы обнаружите, что не будете в действительности нуждаться в этом столько, сколько можете подумать. Несколько хорошо подобранных, общедоступных полей только для чтения, раскрывающих такие функции, могут вам очень помочь. –

1

Я предлагаю исследовать шаблон команды в Java. Он поддерживает функции обратного вызова.

http://en.wikipedia.org/wiki/Command_pattern#Java

+0

Правильно ... в то время как другие языки имеют * указатели на функции * или * делегаты *, Java обрабатывает это через реализацию интерфейса. –

+0

Я бы предпочел иметь дело с интерфейсами, чем указатели на функции C. Какой кошмар. Делегаты несколько лучше. – jn1kk

+0

Простите, что у вас был плохой опыт с указателями функций. Интерфейс - это не что иное, как таблица указателей функций. Если вам нужна целая куча методов, языковая поддержка хороша.Но для одиночных функций, необходимо определить интерфейс, а затем реализовать класс, это просто неуклюже. –

1

Держу пари, вы только что переехали в Java с JavaScript, или какой-либо другой язык, который рассматривает функции как объекты. Насколько мне известно, это невозможно, так как Java не рассматривает функции как объекты. Вам нужно будет написать его в цикле for или какой-либо другой конструкции.

+0

Нет, я не просто перешел с Javascript lol, я просто немного нобе с этими понятиями, но спасибо за ответ в любом случае :) –

+0

Нет проблем. Я перешел с Java на Javascript, и идея передачи функций в качестве параметров сдула меня. Не забудьте ответить +1, если это поможет, даже если вы этого не приняли. – SomeKittens

+0

Не проблема + 1'd действительно ^.^ –

1

Нет, нет синтаксис, как это. Более того, из-за типа erasure фактический тип T не доступен во время выполнения, поэтому он не был бы возможен внутри общего, даже если бы синтаксис был доступен.

Хитрость заключается в том, чтобы передать Class<T> наряду с другими параметрами, и использовать отражение, чтобы получить метод:

joinOnMethod(String separator, Collections<T> items, String methodName, Class<T> theClass) 

Теперь вы можете запросить класс для метода methodName, и использовать этот метод в расчетах. Это не поможет вам уйти от передачи строк (т. Е. Компилятор не будет вызывать ошибку, если метод не существует), но вы можете заставить его работать с дженериками, несмотря на стирание типа.

+1

Это бит, который я хотел избежать, к сожалению, передав имя метода как String. Это может быть опасно при использовании рефлексии, и вы меняете имя в классе, поскольку инструменты для переоснащения не выбирают это:/Мне нужно подумать о чем-то умном для этого :) –