Изучив различные решения на разных форумах и не найдя подходящего решения, я чувствую, что я получил нижний взломанный код, который проще всего отслеживать и кодировать:
Пример. Предположим, у вас есть несколько параметров для перейдите в предложение «IN». Просто поместите фиктивную строку в предложение «IN», скажем, «PARAM» обозначить список параметров, которые будут появляться на месте этой фиктивной строки.
select * from TABLE_A where ATTR IN (PARAM);
Вы можете собрать все параметров в одну переменную String в вашем Java-коде. Это можно сделать следующим образом:
String param1 = "X";
String param2 = "Y";
String param1 = param1.append(",").append(param2);
Вы можете добавить все ваши параметры, разделенные запятыми, в одну переменную String, 'param1', в нашем случае.
После сбора всех параметры в одну строку вы можете просто заменить фиктивный текст в вашем запросе, то есть «PARAM» в этом случае, с параметром String, т. е. param1. Вот что вам нужно сделать:
String query = query.replaceFirst("PARAM",param1); where we have the value of query as
query = "select * from TABLE_A where ATTR IN (PARAM)";
Теперь вы можете выполнить свой запрос с помощью метода executeQuery (). Просто убедитесь, что в вашем запросе нет слова «PARAM». Вы можете использовать комбинацию специальных символов и алфавитов вместо слова «PARAM», чтобы убедиться, что в запросе нет такого слова. Надеюсь, вы получили решение.
Примечание. Хотя это не подготовленный запрос, он выполняет работу, которую я хотел, чтобы мой код выполнял.
Я должен задать вопрос в ответ: Ваш GenSet
"проверяется" или "неконтролируем"? Что это означает?
Проверенный : строгий контроль типов . GenSet
знает явно, какие объекты это содержит (т.е. его конструктора явно вызвали с Class<E>
аргумент, и методы выдадут исключение, когда они будут передаваемыми аргументами, которые не имеют типа E
. См. Collections.checkedCollection
.
-> в этом случае, необходимо записать:
public class GenSet<E> {
private E[] a;
public GenSet(Class<E> c, int s) {
// Use Array native method to create array
// of a type only known at run time
@SuppressWarnings("unchecked")
final E[] a = (E[]) Array.newInstance(c, s);
this.a = a;
}
E get(int i) {
return a[i];
}
}
Неконтролируемый : слабый контроль типов . Никакая проверка типа на самом деле не сделана ни на одном из объектов, переданных как аргумент.
-> в этом случае, необходимо записать
public class GenSet<E> {
private Object[] a;
public GenSet(int s) {
a = new Object[s];
}
E get(int i) {
@SuppressWarnings("unchecked")
final E e = (E) a[i];
return e;
}
}
Примечание, что тип компонента массива должен быть стирание из параметра типа:
public class GenSet<E extends Foo> { // E has an upper bound of Foo
private Foo[] a; // E erases to Foo, so use Foo[]
public GenSet(int s) {
a = new Foo[s];
}
...
}
Все это следует из известного, и преднамеренный, слабость дженериков в Java: это было реализовано с помощью стирания, таким образом, "универсальные" классы не знают, с каким аргументом типа они были созданы во время выполнения и поэтому не могут обеспечить безопасность типов, если некоторый явный механизм (проверка типа) не реализован.
Вы могли создать Объектный массив и бросить его к E везде. Да, это не очень очевидный способ, чтобы сделать это, но это должно, по крайней мере, работать.
Пример использует отражение Java для создания массива. Выполнение этого обычно не рекомендуется, так как это не безопасно с точки зрения типов. Вместо этого что необходимо сделать, просто использовать внутренний Список и избежать массива вообще.
Дженерики Java работают путем проверки типов во время компиляции и вставки соответствующих бросков, но стирание типы в скомпилированных файлах. Это делает универсальные библиотеки применимыми кодом, который не понимает дженериков (который был преднамеренным проектным решением), но что означает, что Вы не можете обычно узнавать то, что тип во время выполнения.
общественность Stack(Class<T> clazz,int capacity)
конструктор требует, чтобы Вы передали Объект класса во время выполнения, что означает, что информация о классе доступна во времени выполнения для кодирования, которому нужен он. И Class<T>
форма означает, что компилятор проверит, что Объектом класса, который Вы передаете, является точно Объект класса для типа T. Не подкласс T, не суперкласс T, но точно T.
Это затем означает, что можно создать объект массива соответствующего типа в конструкторе, что означает, что типу объектов, которые Вы храните в своем наборе, проверят их типы в точке, они добавляются к набору.
Это охвачено в Главе 5 (Дженерики) Эффективный Java, 2-й Выпуск , объект 25... Предпочитают списки массивам
, Ваш код будет работать, хотя он генерирует предупреждение непроверенное (который Вы могли подавить со следующей аннотацией:
@SuppressWarnings({"unchecked"})
Однако, вероятно, было бы лучше использовать Список вместо Массива.
существует интересное обсуждение этой ошибки/функции на стройплощадка OpenJDK .
Вы можете сделать это:
E[] arr = (E[])new Object[INITIAL_ARRAY_LENGTH];
Это один из предлагаемых способов реализации общей коллекции в Эффективной Java; Пункт 26 . Нет ошибок типа, нет необходимости многократно приводить массив. Однако это вызывает предупреждение, потому что это потенциально опасно и должно использоваться с осторожностью. Как подробно описано в комментариях, этот Object []
теперь маскируется под наш тип E []
и может вызывать непредвиденные ошибки или ClassCastException
, если используется небезопасно.
Как показывает опыт, такое поведение является безопасным до тех пор, пока массив приведения используется внутри (например, для поддержки структуры данных), а не возвращается и не предоставляется клиентскому коду. Если вам нужно вернуть массив универсального типа в другой код, то класс Reflection Array
, который вы упомянули, будет правильным решением.
Стоит упомянуть, что везде, где это возможно, вам будет намного приятнее работать с List
, а не с массивами, если вы используете дженерики. Конечно, иногда у вас нет выбора, но использование фреймворка коллекций намного надежнее.
char
с. – Cemafor 20 July 2013 в 00:21