Есть ли способ обойти типизацию лямбда-выражений?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Есть ли способ обойти типизацию лямбда-выражений?

Сообщение Anonymous »

Это вопрос, который меня интересовал, поскольку лямбда-выражения были представлены в Java, и, вдохновленный похожим вопросом, я подумал, что могу поднять его здесь, чтобы посмотреть, есть ли какие-нибудь идеи.
(Примечания: есть аналогичный вопрос для C#, но я не нашел его для Java. Вопросы для Java о «хранении лямбда-выражения в переменной» всегда относятся к случаи, когда тип переменной был исправлен - это именно то, что я пытаюсь обойти)



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

Код: Выделить всё

static void useF(Function f) { ... }
static void useP(Predicate p) { ... }
можно вызывать с помощью одного и того же лямбда-выражения:

Код: Выделить всё

useF(x -> true);
useP(x -> true);
Выражение однажды проявится как класс, реализующий интерфейс Function, и один раз как класс, реализующий интерфейс Predicate< /code> интерфейс.

Но, к сожалению, нет способа сохранить лямбда-выражение с типом, применимым к обеим функциям, как в

Код: Выделить всё

GenericLambdaType

Код: Выделить всё

lambda = x -> true;
Этот «общий лямбда-тип» должен будет кодировать тип метода, который может реализовать с помощью данного лямбда-выражения. . В данном случае это будет

Код: Выделить всё

(Ljava.lang.Integer)Ljava.lang.Boolean

Код: Выделить всё

lambda = x -> true;
(для иллюстрации на основе сигнатур стандартных типов). (Это не совсем необоснованно: лямбда-выражения C++, по сути, делают именно это...)



Так есть ли любой способ предотвратить преобразование лямбда-выражения в один конкретный тип?

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

Код: Выделить всё

useF(theObject);
useP(theObject);
Это маловероятно, поэтому я предполагаю, что ответ будет простым: «Нет», но: может ли существовать какой-либо способ написать < em>общий, волшебный метод адаптации, такой как

Код: Выделить всё

useF(convertToRequiredTargetType(theObject));
useP(convertToRequiredTargetType(theObject));
?



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

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

Код: Выделить всё

static  T provide()
{
return x -> true;
}
конечно, терпит неудачу, заявляя, что «Целевой тип этого выражения должен быть функциональным интерфейсом» (здесь тип просто невозможно вывести ). Но я также рассматривал другие варианты, такие как MethodHandles, жестокие неконтролируемые приведения типов или неприятные хаки с отражениями. Кажется, все пропало сразу после компиляции, где лямбда спрятана в анонимном объекте анонимного класса, единственный метод которого вызывается через InvokeVirtual...

Подробнее здесь: https://stackoverflow.com/questions/363 ... xpressions
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»