Методы Java - использование метода в качестве аргумента - PullRequest
5 голосов
/ 20 мая 2009

Я наткнулся на некоторый код, которым не могу поделиться здесь, но он объявляет метод WITHIN список параметров другого метода. Я даже не знал, что это возможно. Я действительно не понимаю, почему он это делает. Может, кто-нибудь объяснит мне некоторые возможные варианты использования, которые вы, программист, могли бы использовать для этого? (Примечание: поскольку я не могу показать код, я не ожидаю объяснения в контексте просто в целом)

Связанный:

Какая ближайшая замена для указателя функции в Java?

Ответы [ 12 ]

24 голосов
/ 20 мая 2009

Код выглядел примерно так?

obj.someMethod(myVar,3,new FooObject() {
  public void bar() {
    return "baz";
  }
});

Если это так, то метод не передается другому методу в качестве аргумента, а создается анонимный внутренний класс , и экземпляр этого класса передается в качестве аргумента.

В приведенном выше примере FooObject - это абстрактный класс, который не реализует метод bar(). Вместо создания private class, расширяющего FooObject, мы создаем экземпляр абстрактного класса и предоставляем реализацию абстрактного метода в соответствии с остальной частью кода.

Вы не можете создать экземпляр абстрактного класса, поэтому мы должны предоставить отсутствующий метод для создания полного определения класса. Поскольку этот новый класс создается на лету, он не имеет имени, поэтому анонимный . Как определено внутри другого класса, это анонимный внутренний класс.

Это может быть очень удобный ярлык, особенно для Listener классов, но он может усложнить выполнение кода, если вы увлекаетесь, а определения метода в строке становятся слишком длинными.

4 голосов
/ 20 мая 2009

Вы когда-нибудь видели Функциональную Java ? Это очень интересная библиотека, которая позволяет программировать так, как вы бы это делали в Scala . Я написал об этом libs. Признаюсь, лучше использовать более гибкий синтаксис (замыкания BGGA), такой как Scala.

Использование функциональной Java с функцией высокого порядка, такой как map в списке, у нас есть:

final List<Integer> numbers = list(1, 2, 3, 4, 5);  

List<Integer> c = numbers.map(new F<Integer, Integer>() {  
                 public Integer f(Integer arg) {  
                   return arg * arg;  
                  }  
              });  

Другая полезная библиотека - lambdaj , которая предлагает хорошие способы игры, как в функциональном (FP) программировании. Java имеет ограниченный синтаксис по сравнению с языками FP. Но вы все равно можете воспользоваться некоторыми преимуществами стиля FP, но вы должны быть креативными!

4 голосов
/ 20 мая 2009

В Java нельзя передавать методы в качестве параметров. Мог ли это пройти не метод, а анонимный внутренний класс?

Это может быть полезно для передачи поведения между классами. Google "внедрение зависимости" или "инверсия контроля" для получения дополнительной информации.

3 голосов
/ 20 мая 2009

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

public interface F<A, B> {
  public B f(final A a);
}

Затем вы можете ожидать метод в списке аргументов другого метода:

public List<B> map(List<A> as, F<A, B> f) {
  ...
}

И вы можете вызвать его с помощью анонимного экземпляра этого интерфейса:

map(myList, new F<Integer, String>() {
  public String f(Integer i) {
    return String.valueOf(i);
  }
});

Есть библиотека под названием Функциональная Java , которая использует именно эту идею для большой пользы славного языка Java.

3 голосов
/ 20 мая 2009

с использованием java.lang.reflect.Method

Пример

public void callMethod(Method aMethod, int value) throws Exception {
    aMethod.invoke(this, value);
}

public void print(Integer value) {
    System.out.print(value);
}

public void println(Integer value) {
    System.out.println(value);
}

public void demo() throws Exception {
    Method println = this.getClass().getMethod("println", Integer.class);
    Method print = this.getClass().getMethod("print", Integer.class);
    callMethod(println, 10);
    callMethod(print, 10);
}
1 голос
/ 20 мая 2009

Вы также можете сделать что-то вроде этого:

final Predicate somePredicate = new Predicate<Item>() 
  {
  @Override
  public boolean apply(Item item)
    {
    return item.someProperty().equals(something);
    }
  }

И используйте это так:

List<Item> filteredList = filter(list, somePredicate);

Я делал такие вещи раньше. Я также написал методы, которые используют замыкание для создания и возврата анонимной реализации интерфейса аналогичным образом:

Predicate isSomeColor(final Color color)
  {
  return new Predicate<Shape>() 
    {
    @Override
    public boolean apply(Shape shape)
      {
      return shape.getColor().equals(color);
      }
    }
  }

List<Shape> redShapes = filter(shapes, isSomeColor(Color.RED);

Все это по-прежнему анонимные внутренние классы. Нигде я фактически не называю сам класс, у меня просто есть ссылка на экземпляр класса.

1 голос
/ 20 мая 2009

По сути, это не юридический синтаксис в Java. Возможно, это было создание нового экземпляра анонимного класса?

0 голосов
/ 22 октября 2013

не указатель, но все же вы можете написать встроенные функции с некоторыми хитростями.

проверьте мой ответ в другой теме

0 голосов
/ 20 мая 2009

ближайший к аргументу функции

экземпляр анонимного класса с ровно одним методом.

    Runnable a = new Runnable(){

   run(){
    System.out.println("hello");
        }
    }

  myMethod(a);
0 голосов
/ 20 мая 2009

Ответы выше меняются относительно того, возможно ли это или нет. Возможно ли это через отражение? Возможно ли использование анонимного внутреннего класса? Нам нужно уточнить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...