#java
#java
Вопрос:
Мне пришлось написать эту функцию, которая использует функциональный интерфейс mapper
и сопоставляет элементы стека с типом <R>
. Мой вопрос в том, почему дополнительный общий перед возвращаемым типом Stack<R>
необходим в функции map?
public <R> Stack<R> map(Function<E, R> mapper) {
}
Ответ №1:
Класс может быть универсальным или нет, но каким бы ни был ваш класс public class MyClass
, или public class MyClass<E>
может случиться так, что вы хотели бы предложить метод, который использует универсальный параметр только для себя, который не используют другие методы в вашем классе.
Итак <R>
, здесь :
public <R> Stack<R> map(Function<E, R> mapper) {
}
означает: знайте, что есть определенный параметр, который я буду использовать здесь, но только для этого метода.
он может быть указан так же, как вы это сделали бы в объявлении класса :
public <R extends Serializable> Stack<R> map(Function<E, R> mapper) {
}
например.
В вашем случае этот параметр используется для связывания возвращаемого вами типа с типом, который вы вводите при вводе этого метода: это гарантирует, что если вы предоставите средство отображения типа Function<E, R> , вы получите взамен объект R.
Другим удобным использованием этих «дополнительных» универсальных параметров в методах является динамическая проверка типа возвращаемого объекта. Я часто его использую :
public <T> T myMethod(Class<T> expectedClass, int a, int b) {
...
// My result comes in an object o.
Object o;
if (expectedClass.isInstance(o) == false) {
// ClassCastException
}
return (T)o; // You are sure it has the expected type.
}
Комментарии:
1. Могу ли я добавить несколько «<R>» перед объявлением возвращаемого типа или только один?
Ответ №2:
Каждый раз, когда вы имеете дело с дженериками в Java, вы должны явно сообщить методу (и компилятору), что вы имеете дело с этим. Как сообщить им об этом таким образом, добавив <T>
к сигнатуре метода.
Цитирую по ссылке ниже:
В сигнатуре метода подразумевается, что метод будет иметь дело с универсальным типом T. Это необходимо, даже если метод возвращает void
Это очень поверхностное объяснение, но вы можете прочитать больше здесь и здесь .
Ответ №3:
Первый <R>
описывает тип, который вы можете использовать в сигнатуре метода, поэтому он добавляет заполнитель, который вы можете использовать (в любом случае, это список используемых типов). В Stack<R>
or Function<E,R>
параметр type указывает, что данный универсальный тип должен использоваться из объявленных типов.
Иногда это кажется ненужным, но предположим, вы хотите добавить некоторые ограничения к своему типу.
public <T extends SomeObject amp; Comparable> Stack<T> map(T x)
Будет некрасиво записывать все выражение во все места, где вы хотите их использовать.
Кроме того, если вы используете его, например, как массив, вы не можете сделать это там:
public <T extends SomeObject amp; Comparable> Stack<T> map(T[] x)
Итак, первый — это объявление типа в качестве заполнителя. А остальные — это сторона использования дисперсии. Затем компилятор может проверить, что все в порядке на сайтах вызовов, прежде чем произойдет удаление типа.
Ответ №4:
Он вызывает «Универсальный метод». <R>
Означает тип параметра метода, и он будет определен только при вызове метода.