2016-04-30 4 views
2

На работе мы должны создать отчет для нашего клиента, который несколько раз меняет его параметры в течение недели. Этот отчет создается из одной таблицы в нашей базе данных. Например, представьте таблицу, в которой есть 100 столбцов, и сегодня мне нужно создать отчет с 5 столбцами, но завтра я должен сгенерировать 95 из них. Учитывая это, я создал класс TO со всеми столбцами указанной таблицы, и мой запрос возвращает все столбцы (SELECT * FROM TABLE).Вызывать методы динамически на Java

То, что я пытаюсь создать, является динамической формой для создания отчета. Сначала я подумал о создании простого фрейма со списком столбцов, перечисленных как флажки, и пользователь будет выбирать нужные ему столбцы (конечно, с помощью кнопки «Выбрать все», а другой - «Отменить выбор всех»).

Как все столбцы имеют такое же имя, что и атрибуты класса, я разработал следующий код (я имею Google это):

Class c = Test.class; 

for(int i = 0; i < listOfAttributes.length; i++) 
{ 
    auxText += String.valueOf(c.getMethod("get" + listOfAttributes[i]).invoke(this, null)); 
} 

ли это лучший способ сделать то, что мне нужно к?

Заранее спасибо.

Обс: у геттеров класса TO есть шаблон «getAttribute_Name».

Примечание: Этот вопрос отличается от того, в котором пользователь спрашивает, как вызвать метод, заданный определенным именем. Я знаю, как это сделать. Я спрашиваю, если это лучший способ решить проблему, которую я описал.

+1

Возможный дубликат [Как вызвать метод Java когда задано имя метода как строка?] (http://stackoverflow.com/questions/160970/how-do-i-invoke-a-java-method-when-given-the-method-name-as-a -string) –

+0

Как я уже сказал на заметке: Этот вопрос отличается от того, где пользователь спрашивает, КАК вызвать какой-то метод с определенным именем. Я знаю, как это сделать. Я спрашиваю, если это лучший способ решить проблему, которую я описал. –

+0

Хорошо. Я заберу это. Отмечу, что ваше примечание было добавлено после того, как я впервые просмотрел его. –

ответ

0

Моя Java немного более ограничена, но я считаю, что это так же хорошо, как вы собираетесь использовать отражение.

Class<?> c = Test.class; 

for (String attribute : listOfAttributes) { 
    auxText += String.valueOf(c.getMethod("get" + attribute).invoke(this, null)); 
} 

Но так как это звучит, как это из потенциально ненадежных данных, я бы рекомендуем использовать в данном случае HashMap, причем каждый метод явно ссылается. Прежде всего, он явно указывает, какие методы можно динамически назвать. Во-вторых, это более безопасный тип, а ошибки времени компиляции лучше, чем ошибки времени выполнения. В-третьих, он, скорее всего, быстрее, поскольку он вообще избегает отражения. Что-то эффект этого:

private static final HashMap<String, Supplier<Object>> methods = new HashMap<>(); 

// Initialize all the methods. 
static { 
    methods.set("Foo", Test::getFoo); 
    methods.set("Bar", Test::getBar); 
    // etc. 
} 

private String invokeGetter(String name) { 
    if (methods.containsKey(name)) { 
     return String.valueOf(methods.get(name).get()); 
    } else { 
     throw new NoSuchMethodException(); 
    } 
} 

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

0
Class c = Test.class; 
for(int i = 0; i < listOfAttributes.length; i++) 
{ 
    auxText += String.valueOf(c.getMethod("get" + listOfAttributes[i]).invoke(this, null)); 
} 

Вы можете сделать это несколько более элегантно с помощью Java Beans, на Introspector и PropertyDescriptor, но это немного более многословно:

Map<String, Method> methods = new HashMap<>(); 
Class c = this.getClass(); // surely? 
for (PropertyDescriptor pd : Introspector.getBeanInfo(c).getPropertyDescriptors()) 
{ 
    map.put(pd.getName(), pd.getReadMethod(); 
} 
// 
for (int i = 0; i < listOfAttributes.length; i++) 
{ 
    Method m = methods.get(listOfAttributes[i]); 
    if (m == null) 
     continue; 
    auxText += String.valueOf(m.invoke(this, null)); 
} 
Смежные вопросы