Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Вызов через invoke


Автор: Alone 21.8.2004, 14:47
Народ, подскажите, как правильно пользоваться invoke?
Допустим я хочу через invoke выполнить вызов Obj.myMethod();
Что для этого надо сделать?
java.lang.reflect.Method m=Obj.myMethod();
m.invoke(Obj.myMethod );
?

Автор: Alone 21.8.2004, 16:04
Конкретизирую вопрос...
Допустим у меня есть вызов auth.SteVisible(false);
после этого идет операция с сетью, и етесственно объект auth как бы замораживается... т.е. перерисовки (скрытия) не происходит.
Код

try{
           java.lang.Class _class=auth.getClass();

//             Object[] args_value = { new ?????? };  // надо передать false в качестве параметра
            java.lang.Class[] args_class = { java.lang.Class.forName ("???????") };
           java.lang.reflect.Method m=_class.getMethod("setVisible", args_class );
           m.invoke(_class, args_value);
       }catch(Exception e){
             System.out.println(e.getMessage() );
       }
}

Автор: Domestic Cat 21.8.2004, 22:57
Ну вот так, например

Код

import java.lang.reflect.*;

class MyClass
{
   public void method(int n)
   {
       for (int i = 0; i < n; i++)
       {
           System.out.println("Hello, world-" + i);
       }
   }
   
}

public class Test
{
   public static void main(String [] arg) throws Exception
   {
       MyClass myClass = new MyClass();
       Method method = MyClass.class.getMethod("method", new Class [] { int.class });
       Object[] args = new Object[1];
       Object value = new Integer(3);  
       args[0] = value;      
       method.invoke(myClass, args);
   }
}


Для boolean будет соответственно boolean.class и new Boolean(false);

http://www-106.ibm.com/developerworks/java/library/j-dyn0603/
http://www-106.ibm.com/developerworks/java/library/j-dyn0715.html

Автор: DarkDS 22.8.2004, 01:12
Уже как то постил... Надеюсь поможет smile.gif

Если пакет и классы уже есть класспасе, то делается все просто:

Код

String pakName = "com.test.";
String className = "Test";
try
{
  //Get panel class
  Class pClass = Class.forName( panelClassName );
/*
//Если у класса нет коснтруктора, без параметров, но известен конструктор с конечным числом
//параметров.(к примеру есть 2-а параметра и известны их классы). Если не понятно - объясню
  Constructor constructor = pClass.getConstructor( new Class[]{классПараметра1,классПараметра2 } );
  Object o = constructor.newInstance( new Object[]{параметр1, параметр2} );
*/
  Object o = pClass.newInstance();
  Class fClass = o.getClass();
  Method method = fClass.getMethod( methodName, new Class[]{} ); //Нет параметров... Иначе new Class[]{классПараметра1,классПараметра2 }
  Object obj = method.invoke( object, new Object[]{} ); //Нет параметров... Иначе new Object[]{параметр1, параметр2}
//Полученный obj - результат вызова метода
}
catch ( Exception e )
{
  //Error
  e.printStackTrace();
  removeAll();
}


Добавлено @ 01:13
+ еще была тема smile.gif
http://forum.vingrad.ru/index.php?showtopic=25311&hl=getmethod

Автор: Alone 25.8.2004, 09:09
Domestic Cat Пасиб за пример. примерно таким путем и шел, но стопорнулся на классе типа boolean... sad.gif
Теперь все стало на свои места.


DarkDS Вот! Именно этот постинг я и искал по форуму... Пасиб! smile.gif

Автор: Alone 25.8.2004, 11:00
Цитата(Domestic @ 21.8.2004, 22:57)
Код

import java.lang.reflect.*;

class MyClass
{
   public void method(int n)
   {
       for (int i = 0; i < n; i++)
       {
           System.out.println("Hello, world-" + i);
       }
   }
   
}

public class Test
{
   public static void main(String [] arg) throws Exception
   {
       MyClass myClass = new MyClass();
       Method method = MyClass.class.getMethod("method", new
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Class [] { int.class });
       Object[] args = new Object[1];
       Object value = new Integer(3);  
       args[0] = value;      
       method.invoke(myClass, args);
   }
}


Можно уточнить?
Что за метод class у объекта MyClass ???

Автор: DarkDS 25.8.2004, 11:08
Это статик переменная, которая идет от Object и инициализированная классом текущего объекта.
То есть class у MyClass инициализированна структурой java.reflection.Class, которая описывает MyClass smile.gif
Точно такую же структуру вернет вызов метода myClass.getClass();
smile.gif

Автор: Alone 25.8.2004, 13:06
Насчет getClass согласен, а вот переменной class у моего объекта (public class authPanel extends javax.swing.JPanel ) нет.

Автор: DarkDS 25.8.2004, 15:48
Она есть у всех объектов smile.gif Это одна из особенностей языка smile.gif
Добавлено @ 15:50
А javax.swing.JPanel наследуется от объекта (не в прямую а через других родительские классы), как и все классы в яве. Так вот у объекта встроена статическая переменная класс smile.gif

Автор: Alone 26.8.2004, 10:38
Блин... sad.gif
Вот отрывок из кода
Код

       //auth.setVisible(false);    //было

       // стало
       java.lang.Class _class=auth.getClass();
       try{
           java.lang.reflect.Method m=_class.getMethod("setVisible", new Class [] {boolean.class});
           Object [] args=new Object[1];
           Object value=new Boolean(false);
           args[0]=value;
           m.invoke(_class, args);
       }catch (Exception e){
           System.out.println("Exception e="+e.getMessage());
       }

при выполнении получаем
Exception e=object is not an instance of declaring class

Автор: DarkDS 26.8.2004, 10:44
У тебя ошибка в m.invoke(_class, args);
Там должно быть m.invoke(auth, args);
Так как первым аргументом должен быть инстансированный объект нужного тебе класса smile.gif

Автор: Alone 26.8.2004, 10:48
Да, действительно.
Но поблема остается...
метод setVisible(false) объекта auth не вызывается... Объект остается замороженным, до окончания работы с сетью. sad.gif

Автор: AntonSaburov 26.8.2004, 10:48
А на какой строке падает ?

Автор: Alone 26.8.2004, 10:50
с помощю дебага выяснил, что метод setVisible(false) вызывается, но не понимаю, почему объект не перерисовывается???
Добавлено @ 10:54

вот отладочный метод объекта auth, который я вызывал через invoke
вместо setVisible(false)
Код
public void Hide(boolean a){
       System.out.println("Has called hide()");
       mainObj.auth.setVisible(false);
       mainObj.jPanel1.updateUI();
   }

в дебаговый вывод он мне пишет, что метод был вызван. Тоесть типа Ок.
но до окончания работы с сетью (чтение/запись в сокет) это где то около 3-5сек
объект остается на экране как и прежде, с нажатой кнопкой... sad.gif

Автор: DarkDS 26.8.2004, 10:59
У тебя работа с сетью идет в том же треде что и свинги работают?

Автор: Alone 26.8.2004, 11:11
Нет. Для чтения сокета у меня отдельный тред.
Отправка в сокет идет, правда, в этом же треде... Это как то повлияет?
Хотя отправляется очень малое кол-во байт...
вот кусок кода
Код
       java.lang.Class _class=auth.getClass();
       try{
           java.lang.reflect.Method m=_class.getMethod("Hide", new Class [] {boolean.class});
           Object [] args=new Object[1];
           Object value=new Boolean(false);
           args[0]=value;
           m.invoke(auth, args);
       }catch (Exception e){
           System.out.println("Exception e="+e.getMessage());
       }

       /* по логике, в этот момент объект auth уже должен скрыться...*/

       // стартуем нитку чтения сокета
       thred.start();

       // стартуем пинговалку
       pingThread.start();
     
       // отправляем запрос        
       String req;
       req="GETCONFIG=1";
       conn.SendTpkt(req);
       
       // ...и ждем ответа
       synchronized(configLock){
           try{
               System.out.println("getConfig has blocked");
               configLock.wait();
           }catch (InterruptedException e){
               
           }
       }
       System.out.println("getConfig has unblocked");

Автор: DarkDS 26.8.2004, 11:46
Это у тебя происходит в каком то из Листенеров как я понимаю?

Автор: Alone 26.8.2004, 11:58
нет. это вызов по иерархии
main()->creatAllObjects()->prestart()->begin()

Автор: DarkDS 26.8.2004, 14:08
Просто такое чуство что твое ожидание ответа тормозит весь эвент кью. В итоге просто сообщения об обработки событий не доходят до назначения

Автор: Domestic Cat 26.8.2004, 15:26
Здесь рефлекшн вообще не нужен, он ведь делаeт то же самое что и просто setVisible().
А что проиcxодит в этом самом auth? Проблема здесь не в потоке, который вызывает setVisible(), а
в другом треде. Может код для него посмотрим?

Автор: DarkDS 26.8.2004, 16:22
Скорее всего проблемма вот в этом:
Код

      synchronized(configLock){
          try{
              System.out.println("getConfig has blocked");
              configLock.wait();
          }catch (InterruptedException e){
             
          }
      }

То есть программа не выходит из этой процедуры. А если это работает в одном треде с евент кью, то скорее всего сам эвент кью будет заторможен smile.gif

Автор: Alone 26.8.2004, 16:38
Тоесть получается нельзя располагать в одном треде invoke и obj.wait() ???
И еще: если можно, на пальцах, что такое рефлексия?

Автор: Domestic Cat 26.8.2004, 16:53
Я так понял, что проблема в том, что вызов setVisible() не дает желаемого результата.
Поскольку он идет до synchronized, то synchronized никак на него не влияет. Еще раз - проблема в замораживании треда с synchronized, или с бездействием setVisible?
Добавлено @ 16:56

Цитата(Alone @ 26.8.2004, 07:38)
Тоесть получается нельзя располагать в одном треде invoke и obj.wait() ???


Да почему нельзя? Можно.

Цитата(Alone @ 26.8.2004, 07:38)
если можно, на пальцах, что такое рефлексия?

Рефлекшн нужен чтобы:

-Determine the class of an object.
-Get information about a class's modifiers, fields, methods, constructors, and superclasses.
-Find out what constants and method declarations belong to an interface.
-Create an instance of a class whose name is not known until runtime.
-Get and set the value of an object's field, even if the field name is unknown to your program until -runtime.
-Invoke a method on an object, even if the method is not known until runtime.
-Create a new array, whose size and component type are not known until runtime, and then modify the array's components.

Автор: Alone 26.8.2004, 17:13
еще до использования synchronized, setVisible нормально отрабатывал только после завершения операций с сетью. Тоесть на несколько секунд происходит замораживание объекта auth с состоянием нажатой кнопки...
объект представлен в виде панели с авторизационной формочкой и кнопкой
после чтения данных с сокета и их обработки, объект благополучно исчезает и прорисовывается следующий... Вот это меня и злит... sad.gif
Хотя действия выполняются последовательно. Код в топике приведен.

Я хочу найти такй способ , чтоб мои объекты прорисовывались независимо от сетевых задержек (там где это присутствует)

Автор: Domestic Cat 26.8.2004, 17:25
А можно весь код для auth? Здесь есть только метод Hide

Автор: Alone 26.8.2004, 17:45
Там в принципе ничего такого...
Метод Hide я делал для отладки, когда с invoke тренировался... Он не нужен. там прямой вызов auth.setVisible(false)
вот как выполняется код:
Код

main() {
createAllObjects();
prestart();
}

// рисуем форму аутентификации
// поля логин пароль и кнопка
public void preStart(){
       auth.setVisible(true);
       jLabel1.setVisible(true);
}

часть кода из auth
Код

// когда юзер нажмет кнопку:
public void onOk(){
       infoLbl.setVisible(false);
       if(loginFld.getText().compareToIgnoreCase("")!=0 && passwdFld.getPassword().toString().compareToIgnoreCase("")!=0 )
           AuthUser(loginFld.getText(), passwdFld.getPassword().toString() );
       else{
           infoLbl.setText("Неверный ввод !");    
           infoLbl.setVisible(true);
       }
       updateUI();
   }
   

   public void AuthUser(java.lang.String login, java.lang.String password) {
       
       try{
           mainObj.conn.Connect();
       }
       catch (Exception e){
           //mainObj.mon.toLog(e.getMessage());
       }
       
       if (mainObj.conn.isConnected()) {
           
           String req="";
           req+="LOGIN="+loginFld.getText();
           char[] i=passwdFld.getPassword();
           String a="";
           for (int k=0; k<i.length; k++) { a+=i[k]; }
           req+="; PASSWORD="+a;
           //System.out.println(a );
           mainObj.conn.SendTpkt(req);
           
           
           if (checkAuth()){
               resetAuthData();
               mainObj.begin();
^^^^^^^^^^^^^^^^^^^^ вот интересующая часть
           }else{
               resetAuthData();
               mainObj.conn.DisConnect();
               infoLbl.setText("Ошибка авторизации");
               infoLbl.setVisible(true);
           }
       }else{
           infoLbl.setText("Немогу соединиться с сервером");
           infoLbl.setVisible(true);
       }
}

   public boolean checkAuth() {
       
       //System.out.println("In CheckAuth");
       
       String tpkt=new String();
       int len=mainObj.conn.ReadTpkt();
       //System.out.println("len="+len);
       
       if ( len>0) {
           String buf=new String();
           try {
               buf=mainObj.conn.ReadMsg(len);
               //System.out.println("buf="+buf);
               
               if (buf.indexOf("OK", 0)!=-1 ){
                   return true;
               }
           }catch (Exception e) {
               //mainObj.mon.toLog(e.getMessage() );
           }
       }
       return false;
   }


При удачной авторизации возвращаемся в майн код
Код
   public void begin(){
       auth.setEnabled(false);
       auth.setVisible(false);
       jLabel1.setVisible(false);
       /*
       java.lang.Class _class=auth.getClass();
       try{
           java.lang.reflect.Method m=_class.getMethod("Hide", new Class [] {boolean.class});
           Object [] args=new Object[1];
           Object value=new Boolean(false);
           args[0]=value;
           m.invoke(auth, args);
       }catch (Exception e){
           System.out.println("Exception e="+e.getMessage());
       }
       */
       thred.start();
       
       pingThread.start();
       
       String req;
       req="GETCONFIG=1";
       conn.SendTpkt(req);
       
       synchronized(configLock){
           try{
               System.out.println("getConfig has blocked");
               configLock.wait();
           }catch (InterruptedException e){
               
           }
       }
       System.out.println("getConfig has unblocked");
       
       req="GETABOOK=1";
       dwnPanel.setStatus("Загрузка данных...");
       conn.SendTpkt(req);
       synchronized(abookLock){
           try{
               System.out.println("abook has blocked");
               abookLock.wait();
           }catch (InterruptedException e){
           }
       }
       System.out.println("abook has unblocked");

       /* прорисовка остальных форм*/
}


Автор: DarkDS 26.8.2004, 18:36
Код

public void onOk(){
      infoLbl.setVisible(false);
      if(loginFld.getText().compareToIgnoreCase("")!=0 && passwdFld.getPassword().toString().compareToIgnoreCase("")!=0 )
          AuthUser(loginFld.getText(), passwdFld.getPassword().toString() );
------------------
      else{
          infoLbl.setText("Неверный ввод !");    
          infoLbl.setVisible(true);
      }
      updateUI();
  }

Происходит из Эвент кью.
То есть у тебя при вызове аутн юзер ожидается завершения этой процидуры (то есть считывание данных)
Это значит что ДО того как считается - ничего прорисовыватся не будет.
Добавлено @ 18:40
По идее самый простой способ - запустить инвок лайтер и из него при успешной авторизации закрывать окно.
Вечером (часа через 3) могу примерный код набросать...
Добавлено @ 18:42
Кстати... Другой вариант - запустить майн.бегин в инвок лайтер. Правда какими пост эффектами это обернется - нужно подумать smile.gif

Автор: Domestic Cat 26.8.2004, 18:44
Решение (по-моему) такое: вынести код с synchronized в отдельный тред.
DarkDS прав, поток не успевает обработать евент до synchronized.

Автор: DarkDS 26.8.2004, 18:48
Цитата(Domestic @ 26.8.2004, 18:44)
DarkDS прав

Просто сам в начале изучения на такие грабли не раз и не два напарывался...

Автор: Domestic Cat 26.8.2004, 18:59
Ну так ... Тоже напарывался - первый раз когда прогресс бар замирал и прорисовывался до
100% только после выполнения треда. Все равно забывается... smile.gif

Автор: Alone 27.8.2004, 10:44
Ребята, хоть я и начинающий smile.gif но позвольте возразить. Тут вы не правы wink.gif
Когда происходит вызов аутн, то первичные операции с сетью
происходят внутри функции аутн(){
conn.connect();
conn.send();
authuser(); которая в свою очередь производит считывание данных с сокета, и если пришло "Ок", то вызывает begin();
}

Цитата
Происходит из Эвент кью.
То есть у тебя при вызове аутн юзер ожидается завершения этой процидуры (то есть считывание данных)
Это значит что ДО того как считается - ничего прорисовыватся не будет.

Естественно. Но считывание то как раз здесь и заканчивается и в метод begin мы попадаем только после отсылки авторизации и получения ответа от сервера.
На этом операции с сетью прекращаются.
Потом я пытаюсь убрать с экрана объект аутн
и продолжать операции с сетью. (подгрузка остальных данных...)

Автор: DarkDS 27.8.2004, 11:24
Объясняю по порядку.
Насколько я понимаю, onOk() вызывается при нажатии на кнопку (то есть из эвент листенера) и вызывается не через Инвок Лайтер.
Значит до завершения этого метода весь Эвент Кью становится колом.
Далее. Из онОк мы вызываем AuthUser(loginFld.getText(), passwdFld.getPassword().toString() );
То есть для завершения онОк мы ждем чтобы выполнилось AuthUser.
В AuthUser есть такой участвок:
Код

if (checkAuth()){
   resetAuthData();
   mainObj.begin();
}

Значит при удачной ауторизации мы ждем когда закончится работа mainObj.begin();
Далее:
Код

public void begin(){
      auth.setEnabled(false);
      auth.setVisible(false);
      jLabel1.setVisible(false); <-- Вот тут мы посылаем месседж в евент кью о том, что нужно перересовать элемент (Хинт - Эвент Кью ожидает когда мы закончим этот метод)

      thred.start();
     
      pingThread.start();
     
      String req;
      req="GETCONFIG=1";
      conn.SendTpkt(req);
     
      synchronized(configLock){ <-- Вот тут мы ожидаем когда считается данные конфига. Значит мы [b]не выйдем отсюда[/b] пока не считаем конфиг.
          try{
              System.out.println("getConfig has blocked");
              configLock.wait();
          }catch (InterruptedException e){
             
          }
      }
      System.out.println("getConfig has unblocked");
     
      req="GETABOOK=1";
      dwnPanel.setStatus("Загрузка данных...");
      conn.SendTpkt(req);
      synchronized(abookLock){ <-- Вот тут мы ожидаем когда считается данные abook. Значит мы [b]не выйдем отсюда[/b] пока не считаем abook.
          try{
              System.out.println("abook has blocked");
              abookLock.wait();
          }catch (InterruptedException e){
          }
      }
      System.out.println("abook has unblocked");

      /* прорисовка остальных форм*/
}

То есть у тебя ничего не будет прорисованно до тех пор, пока все не считается...
Вопросы есть? smile.gif

Автор: Alone 27.8.2004, 11:54
Блин... И крыть нечем...
тогда нужна архитектурная переработка.
Хорошо, ребята, Пасиб за помощь... Думаю топик мона закрывать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)