2014-12-15 2 views
4

Мне нужна помощь с отражением, так как я не могу заставить свой код работать так, как я хочу.Использование отражения в Java

У меня есть следующие:

nrThreads = Utilities.getNumberOfThreads(filePath, propertiesFile); 
testName = Utilities.getTestName(filePath, propertiesFile); 
System.out.println(Utilities.nowDate()); 
System.out.println("Inserting..."); 

switch (testName) 
{ 
case "InsertAndCommit": 
     final InsertAndCommit[] threads = new InsertAndCommit[nrThreads]; 
     for (int i = 0; i < nrThreads; i++) { 
     threads[i] = new InsertAndCommit(); 
     threads[i].start(); 
     }       
     break;    
case "CommitAfterAllInserts": 
     final CommitAfterAllInserts[] threads1 = new CommitAfterAllInserts[nrThreads]; 
     for (int i = 0; i < nrThreads; i++) { 
     threads1[i] = new CommitAfterAllInserts(); 
     threads1[i].start(); 
     } 
     break; 
     default: break; 
} 

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

Я сделал следующее:

Class<?> clazz = Class.forName(testName); 
Constructor<?> ctor = clazz.getConstructor(String.class); 
final Object[] obj = (Object[]) ctor.newInstance(); //this line isn't right, I need to declare the "threads" array (equivalent to: final InsertAndCommit[] threads = new InsertAndCommit[nrThreads];) 

      for (int i = 0; i < nrThreads; i++) { 
       //In this line I need to declare a new "generic constructor" with reflection (equivalent to threads[i] = new InsertAndCommit();) 
       threads[i].start(); 
      } 

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

+0

Это будет иметь смысл только для использования отражения в этом случае, если '' InsertAndCommit' и CommitAfterAllInserts' как реализовать тот же интерфейс, или расширить один и тот же класс. Это так? – markbernard

+0

Да, они оба реализуют Runnable Interface – SaintLike

ответ

2

Я думаю, вы должны полагаться на то, что оба ваших класса на самом деле являются подклассами Thread (я предполагаю это, поскольку вы используете start() в обоих случаях).

  • Вы можете создать массив типа Thread [] и присвоить любой объект подкласса Thread к нему.
  • Вам не нужно искать конструктор, потому что ваш беззазорный конструктор может быть вызван непосредственно из объекта класса.
  • Конструктор всегда дает вам один объект, а не массив объектов. Поэтому вы должны использовать его только внутри цикла, чтобы создать каждый отдельный поток, а не создавать массив.

Так недостающий кусок:

Class<? extends Thread> clazz = (Class<? extends Thread>) Class.forName(testName); 
Thread[] threads = new Thread[nrThreads]; 
for (int i = 0; i < nrThreads; i++) { 
    threads[i] = clazz.newInstance(); 
    threads[i].start(); 
} 
+0

Что делать, если мои классы не распространяются на поток, но реализуют интерфейс Runnable? – SaintLike

+0

Затем вы можете использовать Runnable [] runnables = new Runnable [nrThreads] '. В этом случае, конечно, вы не сможете запускать 'start' непосредственно на своих объектах. Если вы хотите, я могу расширить свой ответ по этому вопросу. – RealSkeptic

+0

Не нужно указывать, tks в любом случае это нормально;) – SaintLike

5

В этой линии я должен объявить новый «универсальный конструктор» с отражением (эквивалент threads[i] = new InsertAndCommit();)

Если вы используете дженерики, то Вам не придется делать это через отражение собственно в что вам не нужно явно работать с объектом конструктора (хотя методы Class.newInstance() и Array.newInstance() являются частью API отражения Java).

Поскольку у вас есть Class<T>, и потому, что оба класс имеет конструктор без параметров, вы можете вызвать clazz.newInstance() создать новый объект, например:

public <T extends Thread> T[] makeArray(Class<T> clazz, int n) throws Exception { 
    T[] res = (T[]) Array.newInstance(clazz, n); 
    for (int i = 0 ; i < n ; i++) { 
     res[i] = clazz.newInstance(); 
     res[i].start(); 
    } 
    return res; 
} 

Demo.

+0

Что делать, если мои классы не распространяются на поток, а реализуют интерфейс Runnable? – SaintLike

+0

@SaintLike вместо этого используйте 'extend Runnable'. – dasblinkenlight

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