Как установить пользовательский конвертер BigDecimal в TextField <BigDecimal>в Wicket 1.5? - PullRequest
3 голосов
/ 29 декабря 2011

Переходя с 1,4 на 1,5, кажется, что есть много недокументированных изменений в дополнение к документированным .

В 1.4 у меня было:

new TextField<BigDecimal>("capitalInput", 
        new PropertyModel<BigDecimal>(model, "capital")) {
    @Override
    public IConverter getConverter(Class<?> type) {
        return new MonetaryBigDecimalConverter();
    } 
};

С1.5, я изменил это так (чтобы соответствовать объявлению getConverter () ):

new TextField<BigDecimal>("capital", 
        new PropertyModel<BigDecimal>(model, "capital")) {
    @Override
    public <C> IConverter<C> getConverter(Class<C> type) {
        return new MonetaryBigDecimalConverter();
    }
};

, который в моей среде IDE отображается как предупреждение о непроверенном назначении.Но затем попытка построить проект на самом деле это ошибка компиляции :

incompatible types
found   : com.company.MonetaryBigDecimalConverter
required: org.apache.wicket.util.convert.IConverter<C>

Пользовательский MonetaryBigDecimalConverter выглядит примерно так (1.5):

public class MonetaryBigDecimalConverter extends BigDecimalConverter {
    @Override
    public String convertToString(BigDecimal value, Locale locale) {
        // ...
    }
}

Как можноЯ снова делаю эту работу?

Ответы [ 3 ]

3 голосов
/ 02 января 2012

Поскольку конвертер Wicket 1.5 имеет параметр общего типа:

IConverter<C>

Обратите внимание, что аргумент типа C #getConverter () не привязан к параметру типа вашего текстового поля, поэтому вы должны проверить запрошенный тип:

new TextField<BigDecimal>("capital", 
        new PropertyModel<BigDecimal>(model, "capital")) {
    @Override
    public <C> IConverter<C> getConverter(Class<C> type) {
        if (type == BigDecimal) {
            return (IConverter<C>) new MonetaryBigDecimalConverter();
        } else {
            return super.getConverter(type);
        }
    }
};

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

0 голосов
/ 25 июня 2018

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

С другой стороны, если бы тип возвращаемого значения был известен при компиляции, то вы могли бы использовать более разумный подход. (Например, когда Компонент был бы универсальным типом, определяющим тип C вместо передаваемого ему параметра):

Component myConverter = new Component<BigDecimal>() {
    @Override
    public IConverter<BigDecimal> getConverter() {
        return new MonetaryBigDecimalConverter();
    }
};

class Component<C> { // <-- Type of C is known at compile time!
    public IConverter<C> getConverter() {
        return null;
    }
}

Поскольку компилятор теперь точно знает, что метод getConverter вернет IConverter<BigDecimal>, приведение не требуется.


Ваше собственное решение извлечения в переменную работает так же, как приведение к необработанному типу IConverter, что также возможно. Не нужно его извлекать.

@Override
public <C> IConverter<C> getConverter(Class<C> type) {
    return (IConverter) new MonetaryBigDecimalConverter();
}

При приведении к необработанному типу вместо того, чтобы сказать «я возвращаю конвертер типа BigDecimal» (что может быть неправильно, если переданный аргумент другого типа), вы теперь говорите «я возвращаю IConverter любого типа» (который стало возможным по причинам обратной совместимости, когда дженерики были введены в Java 1.5, но, конечно, могут выдавать RuntimeException)

0 голосов
/ 29 декабря 2011

Понятия не имею почему, но следующее небольшое изменение в методе getConverter сделало его компиляцией.

@Override
public <C> IConverter<C> getConverter(Class<C> type) {
    IConverter converter = new MonetaryBigDecimalConverter();
    return converter;
}

Я только что извлек экземпляр MonetaryBigDecimalConverter в переменную типа IConverter.Поле или константа будет работать аналогично.(Примечание: тип должен не быть IConverter<C> или IConverter<BigDecimal>.) Этот код по-прежнему выдает предупреждение «непроверенное назначение», но по крайней мере компилируется.

Я был бы признателенесли кто-то добавил объяснение или лучшее решение вообще.Я, конечно, не эксперт, когда дело доходит до странностей дженериков Java.

...