#java #generics #collections
#java #общие сведения #Коллекции
Вопрос:
У меня есть метод на Java, который анализирует некоторые данные из базы данных
ArrayList<Object> nodeList = new ArrayList<Object>();
public void parseResults() throws SQLException, ListEmptyException, NoRecognisableCharacterException{
// parses records from a query. ONLY ONE COLUMN
while(getResultSet().next()){
for(int i = 1; i <= getNumberOfColumns(); i ){
switch(getColumnType()){
//According to the datatype, I call the proper method get[DataType] of resultSet
case 0:throw new ListEmptyException();
case 4:nodeList.add(getResultSet().getInt(i));break;
case 12:nodeList.add(getResultSet().getString(i).trim());break;
default:throw new NoRecognisableCharacterException();
}
}
}
}
Мне сказали не использовать ArrayList<Object>
для хранения данных другого типа. Я должен создать объект, который вместо этого анализирует соответствующий тип данных. Я не хочу перегружать метод для каждого отдельного типа данных (их много), ни создавать отдельные классы, которые просто изменяют один get[DataType]
метод, ни иметь этот switch
цикл внутри for
цикла, ни иметь множественные экземпляры NodeList в соответствии с типом данных. Есть ли способ заставить этот метод работать для каждого типа данных? Должны ли в этом случае использоваться общие файлы? Заранее благодарю вас.
Комментарии:
1. Я не уверен, что понимаю вашу идею, но правильный способ обработки / анализа разных данных из базы данных — использовать отдельные классы для разных данных, загруженных из разных таблиц. Чрезмерная унификация здесь противоречит цели и не помогает и не делает ваш код чистым.
Ответ №1:
Вы можете обернуть свой объект resultset в класс, подобный этому:
public class ObjectWrapper implements Wrapper {
private Object wrappedObject;
public ObjectWrapper(Object wrappedObject) {
this.wrappedObject = wrappedObject;
}
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> paramClass) {
return (T) wrappedObject;
}
public boolean isWrapperFor(Class<?> paramClass) {
return paramClass.isInstance(wrappedObject);
}
public static Wrapper wrap(ResultSet rs, int column, int columnType) throws SQLException {
if (columnType == 0) {
return new EmptyListExceptionWrapper();
} else {
return new ObjectWrapper(rs.getObject(column));
}
}
}
и класс для управления исключениями:
public class EmptyListExceptionWrapper implements Wrapper {
@Override
public <T> T unwrap(Class<T> paramClass) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> paramClass) throws SQLException {
return false;
}
}
Тогда у вас есть
ArrayList<Wrapper> wrapper = new ArrayList<Wrapper>;
Ваш код будет:
while(getResultSet().next()){
for(int i = 1; i <= getNumberOfColumns(); i ){
wrappers.add(ObjectWrapper.wrap(getResultSet(), i, getColumnType()));
}
}
Комментарии:
1. Это было именно то, что я искал!! Но он возвращает такие имена, как
dataBaseConnection.ObjectWrapper@179d3b25
… как я должен это исправить?2. Вы должны переопределить метод toString.
3. Все эти классы-оболочки для меня совершенно новые… не были бы вы так любезны рассказать мне, как именно переопределить
toString()
метод для этого?4.
@Override public String toString() { return wrappedObject.toString(); }