2015-09-28 3 views
1

Скажем, у нас естьКаков тип ссылки на метод?

class A { 
    B method1 (C c) { ... } 
} 

Что это тип method1 в качестве справочного метода?

Это, что метод подписи foo() для этого вызова ?:

foo (A::method1); 

Примечание:

Я определить интерфейс

interface I { 
    B m (A a, C c); 
} 

и, кажется, это правильно объявить foo как

void foo (I i) { } 

(так как он соответствует вызову foo(A::method1) - inside foo вам необходимо написать b=i.m(a,c), что означает b=a.method1(c)).

Это единственный способ пойти?

ответ

3

Ссылки на методы и лямбды задаются в соответствии с типом SAM interfaces. В вашем случае он должен соответствовать I, потому что это аргумент foo.

1

Неформальное объяснение:

Помните, что ссылки на метод можно рассматривать как альтернативный синтаксис для некоторых лямбды, и что лямбды все реализовать один или более functional interfaces.

И помните, что лямбды являются (в настоящее время) способом написания анонимных классов одного метода в гораздо более сжатой форме; таким образом, lambdas всегда можно свести к анонимному классу (но не всегда наоборот).

Так

foo (A::method1); 

может стать

foo ((c) -> <body>); 

, которая может быть сведена к анонимному классу:

foo (new Function<B>() { 
    <body> 
}); 

которого анонимный класс, который является подтипом функции

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


ПСБ на самом деле имеет раздел под названием «15.13.2. Тип эталонного метода», но формулировка может быть немного тупой. Вкратце:

Способ ссылка может быть использован в качестве типа T если:

  • T представляет собой функциональный тип интерфейса (раздел 9.8)
  • абстрактный метод функционального интерфейса соответствует типу время компиляции эталонного метода
  • Либо:
    • Эталонные возвращает void
    • Ссылка возвращает тип, который может быть назначен соответствующий тип функционального интерфейса, например Ссылка метод должен возвращать Number или подтип, чтобы быть совместимым с `B Foo (функция е)
+0

Это не эквивалентно анонимным внутренним классам, потому что lambdas не захватывают $ this как поле – the8472

+0

@ the8472 А, не знал об этом. Принял удар по фиксации, надеюсь, это не так. Спасибо что подметил это! – awksp

0

Я допускающее здесь, что этот вопрос является слишком сложным для меня, чтобы ответить, не пытаясь, но у меня есть попытался понять ваш вопрос, поэтому я понял свое положение - ваш подход прекрасен. В основном вы делаете следующие вещи здесь -

  1. Используя сокращенный синтаксис для имеющих анонимный класс, который реализует функциональный интерфейс- и это хорошо.
  2. Пусть компилятор знает, что использовать A::method1 в качестве реализации I.m - и это прекрасно.
  3. Поскольку A::method1 уже существует, вы можете использовать ссылку на метод вместо выражения лямбда - - это тоже хорошо.
  4. Передача фактического параметра c, который производится в корпусе foo Метод в линии - b=i.m(a,c). Фактический параметр, используемый здесь для c, должен быть передан в A::method1.
  5. Объект a в a.method1 остается произвольное как в Java 8 спецификации для этого синтаксиса, как вы с указанием Class::Method и не Instance::Method
1

Вместо того, чтобы объявить новый интерфейс, который вы можете использовать существующий BiFunction:

void foo(BiFunction<? super A, ? super C, ? extends B> fn) { 
    ... 
    B b = fn.apply(a, c); 
    ... 
} 
Смежные вопросы