Возможно, вопрос был задан раньше, но, как обычно, второй вы упоминаете слово generic, вы получаете тысячу ответов, объясняющих стирание типа. Я давно прошел эту фазу и много знаю о дженериках и их использовании, но эта ситуация немного более тонкая.
У меня есть контейнер, представляющий ячейку данных в электронной таблице, которая фактически хранит данные в двух форматах: в виде строки для отображения, но и в другом формате, в зависимости от данных (хранимых как объект). Ячейка также содержит трансформатор, который преобразует тип, а также проверяет достоверность для типа (например, IntegerTransformer проверяет, является ли строка допустимым целым числом, и если она возвращает целое число для хранения и наоборот).
Ячейка сама не набирается, так как я хочу изменить формат (например, изменить вторичный формат на float вместо integer или на необработанную строку), не перестраивая объект ячейки новым типом. предыдущая попытка использовала общие типы, но не могла изменить тип, который был определен, когда кодирование получилось очень громоздким с большим отражением.
Вопрос в следующем: как я могу получить данные из моей ячейки в типизированном виде? Я экспериментировал и обнаружил, что использование общего типа может быть выполнено с помощью метода, хотя ограничение не было определено
public class Cell {
private String stringVal;
private Object valVal;
private Transformer<?> trans;
private Class<?> valClass;
public String getStringVal(){
return stringVal;
}
public boolean setStringVal(){
//this not only set the value, but checks it with the transformer that it meets constraints and updates valVal too
}
public <T> T getValVal(){
return (T) valVal;
//This works, but I don't understand why
}
}
Бит, который меня отталкивает: это? он не может ничего отличить, нет ввода типа T, который сдерживает его, чтобы соответствовать чему-либо, на самом деле он ничего не говорит нигде. Наличие возвращаемого типа объекта ничего не делает, кроме как придания кастингам сложности.
В моем тесте я установил двойное значение, он сохранил Double (как объект), и когда я сделал Double testdou = testCell.getValVal(); он мгновенно работал, даже без предупреждения о предупреждении. однако, когда я сделал String teststr = testCell.getValVal(), я получил исключение ClassCastException. Неудивительно.
Есть два вида, которые я вижу по этому поводу:
Один: использование undefined Cast to, кажется, не что иное, как бэдж-способ поместить результат внутри метода, а не снаружи после его возвращения. Это очень удобно с точки зрения пользователя, но пользователь метода должен беспокоиться об использовании правильных вызовов: все это происходит, скрывая сложные предупреждения и проверки до времени выполнения, но, похоже, работает.
Вторая точка зрения: мне не нравится этот код: он не чист, это не то качество кода, которое я нормально горжусь письмом. Код должен быть правильным, а не просто работать. Ошибки должны быть пойманы и обработаны, и ожидается, что интерфейсы должны быть надежными, даже если единственным пользователем ожидания является сам, и я всегда предпочитаю гибкий универсальный и многоразовый метод для неудобного. Проблема в том, есть ли нормальный способ сделать это? Является ли это проницательным способом достижения бесприбыльного, все принимающего ArrayList, который возвращает все, что угодно, без кастинга? или здесь что-то мне не хватает. Что-то подсказывает мне, что я не должен доверять этому коду!
возможно, более философский вопрос, чем я предполагал, но я предполагаю, что я прошу.
edit: дальнейшее тестирование.
Я пробовал следующие два интересных фрагмента:
public <T> T getTypedElem() {
T output = (T) this.typedElem;
System.out.println(output.getClass());
return output;
}
public <T> T getTypedElem() {
T output = null;
try {
output = (T) this.typedElem;
System.out.println(output.getClass());
} catch (ClassCastException e) {
System.out.println("class cast caught");
return null;
}
return output;
}
При назначении double to typedElem и попытке поместить его в String я получаю исключение NOT на приведение к, но по возврату, а второй фрагмент не защищает. Выход из getClass - это java.lang.Double, предполагающий, что это динамически выводится из typedElem, но проверки типа уровня компилятора просто вынуждены уйти с пути.
В качестве примечания для обсуждения: существует также функция для получения valClass, что означает возможность выполнения проверки присваивания во время выполнения.
Edit2: result
Подумав о вариантах, которые я отправил с двумя решениями: одно легкое решение, но аннотировало функцию как @depreciated и второе решение, в котором вы передаете ему класс, который вы хотите попробовать сделать. таким образом, это выбор в зависимости от ситуации.