简体   繁体   中英

Using reflection in Java

I need some help with reflection, since I can't make my code work the way I want to.

I have the following:

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;
}

As you can see, I'm repeating code inside this switch/case. I know I can do that piece of code using reflection but I can't seem to get it right.

I've done the following:

 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();
            }

I've been reading a lot about reflection and I can't seem to get this right, can you please help me?

In this line I need to declare a new "generic constructor" with reflection (equivalent to threads[i] = new InsertAndCommit(); )

If you use generics, you do not have to do that through a reflection proper, in the sense that you do not need to work with the constructor object explicitly (although Class.newInstance() and Array.newInstance() methods are part of the Java reflection API).

Since you have Class<T> , and because both classes have parameterless constructors, you can call clazz.newInstance() to create a new object, like this:

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 .

I think you should be relying on the fact that both of your classes are actually subclasses of Thread (I'm assuming this as you're using start() in both cases).

  • You can create an array of type Thread [] and assign any object of a subclass of Thread to it.
  • You don't need to look up the constructor because your the parameterless construcor can be invoked directly from the class object.
  • A constructor always gives you a single object, not an array of objects. So you should use it only inside the loop, to create each individual thread, not to create the array.

So the missing piece is:

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM