Использование переменной-члена необработанного типа, а затем преобразование в соответствующий тип по запросу

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

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

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

Можно также избежать необработанного типа, используя универсальные методы для предоставления таких переменных. Однако это повлечет за собой создание нового экземпляра при каждом вызове.

Вот кусок кода, иллюстрирующий проблему:

import java.util.function.BiFunction;
import java.util.function.Consumer;

public class PreferencesForFruits {

interface Fruit{}
static class Banana implements Fruit {}
static class Apple implements Fruit {}

// a class describing the packaging of a fruit;
// it depends on the type of consumer of the fruit
static class FruitBox<F extends Fruit, C extends Consumer<F>> {
    // constructor (note that it doesn't accept wildcards, 
    // therefore its client must specify fixed types) 
    FruitBox(F f,C c) {}
}

// preferences for apples and bananas specified in two nested classes:
// 
public static class PrefsForApples<AC extends Consumer<Apple>> {
    // a functional object specifying 
    // how to pack a fruit for a customer
    BiFunction<Apple,AC,FruitBox<Apple,AC>> packingBiFunction = 
         (Apple a, AC ac) -> new FruitBox<Apple,AC>(a,ac);
}
//
public static class PrefsForBananas<BS extends Consumer<Banana>> {
    // ......
}

// convenience methods to obtained preferences;
// the argument is used here only to fix the generic type of the output
//
static <AC extends Consumer<Apple>> 
PrefsForApples<AC> newPrefsForApples(AC appleConsumer) {
    return new PrefsForApples<AC>();
}
//  
static <BC extends Consumer<Banana>> 
PrefsForBananas<BC> newPrefsForBananas(BC bananaSupplierDummy) {
    return new PrefsForBananas<BC>();
}

/*
 *  Now using fields of raw type to avoid creation of distinct instances  
 */

// Here are the raw type variables mentioned in the question:
private PrefsForApples prefsForApples;
private PrefsForBananas prefsForBananas;

// the convenience methods convert the raw type 
// to the required type 

<AC extends Consumer<Apple>> 
PrefsForApples<AC> prefsForApplesRaw(AC appleConsumer) {
    return (PrefsForApples<AC>) prefsForApples;
}

<BC extends Consumer<Banana>> 
PrefsForBananas<BC> prefsForBananasRaw(BC bananaSupplierDummy) {
    return (PrefsForBananas<BC>) prefsForBananas;
}

person stefano casadei    schedule 20.03.2019    source источник
comment
В большинстве случаев вы можете использовать <?> вместо необработанного типа.   -  person Karol Dowbecki    schedule 20.03.2019
comment
@KarolDowbecki, что похоже на root для всех дженериков, это вряд ли что-то решит   -  person Eugene    schedule 20.03.2019
comment
@Eugene Я думаю, это даст еще несколько проверок компилятора, не намного, но лучше, чем необработанный тип.   -  person Karol Dowbecki    schedule 20.03.2019
comment
@Karol На самом деле похоже, что метод prefsForApplesRaw работает одинаково хорошо после добавления <?> к prefsForApples, так что, вероятно, здесь нет необходимости использовать необработанные типы. Я ошибся, думая, что приведение (PrefsForApples<AC>) применимо только к необработанному типу. Но я все еще не могу избавиться от вышеупомянутого непроверенного броска, кажется. Итак, я думаю, мой вопрос должен был быть: есть ли способ избежать этого непроверенного приведения? В каких случаях это может быть небезопасно?   -  person stefano casadei    schedule 20.03.2019