от
У меня есть абстрактный класс с универсальными типами уровня класса
. В нем есть метод, который принимает
O
и
BiFunction, String>
. В этом методе определено обобщение
.
public interface ParamDescription {
    //...
     String getParamString(O obj, BiFunction, String> objectToString);
}
Затем у меня есть три класса, которые реализуют этот интерфейс по-разному, но все они имеют переменные
Class
и
Class
. Два также имеют несколько дополнительных обобщенных типов на уровне класса и переменные
Class<>
, которые идут вместе с ними. Во всех них я пытаюсь вызвать этот метод objectToString, используя объект одного из универсальных типов уровня класса и связанную с ним переменную класса. Вот самый простой:
Function<? super O, P> getter;
Class paramClass;
public  String getParamString(O obj, BiFunction, String> objectToString) {
    return objectToString.apply(getter.apply(obj), paramClass);
}
Однако, когда я пытаюсь скомпилировать это, я получаю это:
error: method apply in interface BiFunction cannot be applied to given types;
        return objectToString.apply(getter.apply(obj), paramClass);
                             ^
  required: B,Class
  found: P,Class
  reason: argument mismatch; P cannot be converted to B
  where B,O,P,T,U,R are type

В этом примере я мог бы решить эту проблему, изменив B
s на
P
s. Однако это не работает для двух других реализаций. В двух других реализациях мне нужно использовать несколько общих типов, о которых интерфейс не знает. Единственное реальное ограничение, которое у меня есть, заключается в том, что параметр
Class
, предоставленный для BiFunction, должен соответствовать параметру
B
, который также ему присвоен. По сути, «вот объект, а вот его тип». Я попытался создать вспомогательную функцию, как это
public  String getParamString(O obj, BiFunction, String> objectToString) {
    return paramToString(obj, objectToString);
}
public String paramToString(O obj, BiFunction, String> objectToString) {
    return objectToString.apply(getter.apply(obj), paramClass);
}
Но это не понравилось кастинг на BiFunction. Я также попробовал реальный кастинг вот так:
public  String getParamString(O obj, BiFunction, String> objectToString) {
    return objectToString.apply((B)getter.apply(obj), (Class)paramClass);
}
Но это дает неконтролируемые предупреждения для обоих типов, и я не знаю достаточно, чтобы знать, действительно ли это безопасно или нет. Насколько я понимаю, это в основном просто бросило бы первое в Object, а второе - в Class Является ли применение и подавление предупреждений подходом или есть лучший путь? Для справки, вот мои две другие реализации:
//Class level: >
Class objClass;
Class paramClass;
Class entryClass;
Function<? super O, P> getter;
public  String getParamString(O obj, BiFunction, String> objectToString) {
    P collection = getter.apply(obj);
    if (collection == null) {
        return objectToString.apply(collection, paramClass);
    }
    return collection.stream()
                     .map(e 

а также

//Class level: >
Class objClass;
Class paramClass;
Class keyClass;
Class valueClass;
Function<? super O, P> getter;
public  String getParamString(O obj, BiFunction, String> objectToString) {
    P map = getter.apply(obj);
    if (map == null) {
        return objectToString.apply(map, paramClass);
    }
    return map.entrySet()
              .stream()
              .collect(Collectors.toMap(e 

Обновите 1 с большим количеством вещей, которые я попробовал, но это не сработало:

Я попытался установить цель:

public  String getParamString(O obj, BiFunction, String> objectToString) {
    return objectToString.apply(getter.apply(obj), paramClass);
}
Но это все еще дает
required: B,Class
found: P,Class
reason: argument mismatch; P cannot be converted to B
Я попытался использовать подстановочный знак вместо
B
:
public String getParamString(O obj, BiFunction<?, Class<?>, String> objectToString) {
    return objectToString.apply(getter.apply(obj), paramClass);
}
с такими же результатами:
required: CAP#1,Class<?>
found: P,Class
reason: argument mismatch; P cannot be converted to CAP#1
Похоже, что явное приведение и подавление предупреждений может быть единственным способом.
@SuppressWarnings("unchecked")
public  String getParamString(O obj, BiFunction, String> objectToString) {
    return objectToString.apply((B)getter.apply(obj), (Class)paramClass);
}
Это расстраивает, хотя, потому что я тогда теряю проверку во время компиляции, что предоставленный класс (2-й параметр) представляет класс 1-го параметра. Но он работает, и в противном случае он ведет себя правильно. Обновление 2 с тем, что я пошел с Так как приведение было единственным способом, которым я мог заставить его фактически работать, и это удаляет проверку, упомянутую выше, я решил просто избавиться от универсального типа
B
в целом. Мой интерфейс имеет это:
String getParamString(O obj, BiFunction
objectToString); и мои реализации выглядят так:
public String getParamString(O obj, BiFunction
objectToString) { return objectToString.apply(getter.apply(obj), paramClass); } а также
public String getParamString(O obj, BiFunction
objectToString) { P collection = getter.apply(obj); if (collection == null) { return objectToString.apply(collection, paramClass); } return collection.stream() .map(e а также
public String getParamString(O obj, BiFunction
objectToString) { P map = getter.apply(obj); if (map == null) { return objectToString.apply(map, paramClass); } return map.entrySet() .stream() .collect(Collectors.toMap(e Затем, при вызове этих функций я должен подавлять предупреждения, но это из-за того, как я создаю бифункцию. Я создаю его, используя другой метод, который принимает метод общего типа
P
и
Class
, который приводится к
Object
и необработанному NBqRL0XvP4THL3GGFFHGGMGFXGHGGMGGGMXGGMGFXFXGMXGMGMXGMXGMXGMXGMXGMXGMXGMXGMXXXXXXXXBXBXBXBXBXBXBXA Однако, на мой взгляд, это лучше, чем создавать и подавлять предупреждения при каждом использовании BiFunction. В итоге: я заставил это работать, но я не смог сделать это таким образом, чтобы обеспечить защиту, которую я хотел.              

Ваш ответ

Отображаемое имя (по желанию):
Конфиденциальность: Ваш электронный адрес будет использоваться только для отправки уведомлений.
Анти-спам проверка:
Чтобы избежать проверки в будущем, пожалуйста войдите или зарегистрируйтесь.

1 Ответ

0 голосов
от
Краткий ответ: не используйте универсальный тип
B
для этого метода. Подробности: Невозможно сказать компилятору, что для данного вызова
P
(или некоторый другой универсальный тип) следует рассматривать как
B
, кроме приведения:
return objectToString.apply((B)getter.apply(obj), (Class
Добро пожаловать на сайт ByNets, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...