2013-10-01 1 views
0

Я принимаю в массиве методов, и я хочу, чтобы приковать их вместе, чтобы изменить объект, который я работаю в.Java отражение вложенные методы не изменяя основной объект

Например я начинаю с

"getStuff().get(1).get(3).setMoreStuff().put(stuff,6)" 

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

Object res = this; 
String[] methods = targetString.split("\\.(?=\\D)"); 
for (String m : methods){ 

    List<Object> params = new ArrayList<Object>(); 
    List<Object> params = new ArrayList<Object>(); 

        for (String p : m.split("\\(|,|\\)")) { 
         try { 
          if (p.indexOf(".") != -1){ 
           double tempD = Double.parseDouble(p); 
           params.add(tempD); 
          } else { 
           int tempP = Integer.parseInt(p); 
           params.add(tempP); 
          } 
         } catch (Exception ex) { //not a number 
          params.add(p); 
         } 
        } 
    switch (params.size()) { 
     case 1: 
      res = res.getClass().getMethod(
          params.get(0) 
            ).invoke(res); 
      break; 
     case 2: 
      res = res.getClass().getMethod(
          params.get(0), 
          params.get(1).getClass() 
            ).invoke(res, params.get(1)); 
      break; 
     case 3: 
      res = res.getClass().getMethod(
          params.get(0), 
          params.get(1).getClass(),   
          params.get(2).getClass() 
            ).invoke(res, params.get(1), params.get(2)); 
           break; 
    } 

В заключение я заметил, что res был изменен так, как я ожидал. Все геттеры и сеттеры называются правильно. Но, конечно, базовый объект, на который это ссылается, не был изменен!

Я предполагаю, что я просто называю геттеры и сеттеры копии, которую я сделал в первой строке!

теперь я не могу просто использовать

this.getClass().getMethod(...).invoke(...) 

потому что мне нужно, чтобы вызвать тот же getMethod объекта, возвращенного этим вызовом.

Для уточнения:

Object res = this; 

создает "указатель" на это. Поэтому, когда я позвоню

res.getStuff().setStuff(foo) 

это также будет изменено.

, но, кажется, что, когда я называю

res = res.getStuff(); 
res = res.setStuff(); 

, как я в моем цикле, это не меняет основной объект это относится к?

Редактировать: Включено больше кода в соответствии с запросом.

Edit2: добавлен пример пыльника, чтобы прояснить мою проблему.

Edit3: пытался добавить больше кода, его немного трудно добавить рабочую программу без включения в каждый класс

+1

Похоже, это должно быть хорошо для меня. Вы вообще не копируете объект.Пожалуйста, покажите короткую, но * полную * программу, демонстрирующую проблему. (Возможно, вам захочется немного упростить код, например, вызывать только один метод или поддерживать только методы без параметров.) –

+0

Я добавил еще несколько строк кода. Но все они кажутся довольно несвязанными. Линия, которая меня беспокоит, находится внутри коммутатора, где я устанавливаю res = res.getClass(). GetMethod (...). Invoke (...) – Ervin

+1

Я не просил «еще несколько строк кода». Я попросил короткую, но полную программу, демонстрирующую проблему - что-то, что мы можем запустить, чтобы помочь вам диагностировать проблему. Пожалуйста, прочитайте http://tinyurl.com/so-hints –

ответ

2

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

import java.lang.reflect.*; 

class Person { 
    private String name = "default"; 

    public String getName() { 
     return name; 
    } 

    // Obviously this would normally take a parameter 
    public void setName() { 
     name = "name has been set"; 
    } 
} 

class Test { 

    private Person person = new Person(); 

    public Person getPerson() { 
     return person; 
    } 

    // Note that we're only declaring throws Exception for convenience 
    // here - diagnostic code only, *not* production code! 
    public void callMethods(String... methodNames) throws Exception { 
     Object res = this; 
     for (String methodName : methodNames) { 
      Method method = res.getClass().getMethod(methodName); 
      res = method.invoke(res); 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     Test test = new Test(); 
     test.callMethods("getPerson", "setName"); 
     System.out.println(test.getPerson().getName()); 
    } 
} 

Выхода «задано имя» так же, как я ожидал. Посмотрите, можете ли вы немного упростить свой код, удалив дополнительные зависимости и т. Д., Пока у вас не будет чего-то похожего короткого, но полного, но которое не работает. Я подозреваю, что вы действительно найдете проблему, когда идете.

+0

Спасибо Jon. После нескольких часов отладки я обнаружил, что один из методов get, который я вызывал таким образом, не возвращал основной объект, но возвращал копию, используя новое ключевое слово. Спасибо за помощь! – Ervin

0

объект не меняет ссылку, ее изменения VALUE. Поэтому, если вы вызовете this.get («некоторый ключ»), вы получите значение, равное тому же значению, которое вы положили с помощью отражения.

Справа?

+0

Я не уверен, что понимаю, что вы пытаетесь сказать. Я могу вызвать каждый метод get и put для каждого метода в массиве. На каждом шаге я вижу, что переменная res изменяется, но ни в коем случае у меня нет объекта, который охватывает все изменения, вызванные этими методами. Вы пытаетесь сказать мне, что каждый раз, когда я вызываю оператор присваивания по res, я создаю новый объект? – Ervin

Смежные вопросы