Unhandled Exception Type: InstantiationException at process.org

I am trying to do a simple Class.newInstance () from within the processing, but I am failing :(

EDIT: As stated below, the reason it didn't work is because the processing wraps all of the code in a class that makes all declared classes inner classes. Java The language specification states that newInstance () for inner classes should be passed a reference to the container class, so after changing, calling newInstance to newInstance (this); he worked as intended.

Sample code below where it throws an Instantiation exception.

Docs said it has a public constructor and everything will be fine, but alas.

current processing 2.2.1

Codeflow: it populates the list of all classes that implement the interface. then we go through state.runnableTypes and try (but can't) instantiate a new instance of that type.

Please, help?

(apologies for the clunky state variable, has to do with the even more clunkier ryo unit test system;))

    State state;
/* It nicely finds the Wtf class and inserts that into its classes array, 
 * but when i try to instantiate a new one, whatever I try, it throws :(
 */
void setup() {
  size(1024, 768, P3D);
  noLoop(); 
//get all the classes
  state = new State();
  Class[] types = this.getClass().getDeclaredClasses();
  state.allTypes = types;

  //enumerate castable types
  for (int i = 0, l = types.length; i<l; i++) { 
    Class c = types[i];
    if ( !c.isInterface() && IMenuRunnable.class.isAssignableFrom(c) ) { 
      println("adding "+c.toString());
      state.runnableTypes.put(c.getSimpleName(), c);
    }
  }

  //loop through the list and create some instances //FIXME: Exception handling ;p
  for ( String s : state.runnableTypes.keySet () ) { 
    Class c = state.runnableTypes.get(s);
    IMenuRunnable u = (IMenuRunnable) c.newInstance(); // ERR: calling Class.newInstance() here throws an error??
    java.lang.reflect.Constructor[] ctors = c.getConstructors();
    for ( java.lang.reflect.Constructor ctor : ctors ) { 
      ctor.setAccessible(true);
      Object o = ctor.newInstance(); // ERR: going via constructor array, same error :(
    }
  }
}




void draw() { 
  background(0);
}




class State {
  Class[] allTypes;
  HashMap<String, Class> runnableTypes = new HashMap<String, Class>();
}



interface IMenuRunnable {
}



public class Wtf implements IMenuRunnable { 
  public Wtf() {
  }
}

      

+3


source to share


1 answer


First of all, your code won't compile because you need to wrap newInstance()

in a try / catch block. The function newInstance()

can call InstantiationException

or IllegalAccessException

, so you need to catch these Exceptions. It is your fault that tells you.

You're in luck if you post an MCVE like:

void setup() {
  try {
    Class<Wtf> c = Wtf.class;
    IMenuRunnable u = (IMenuRunnable) c.newInstance();
    println(u.toString());
  }
  catch(Exception e) {
    e.printStackTrace();
  }
}

interface IMenuRunnable {}

public class Wtf implements IMenuRunnable{ 
  public Wtf() {
  }
}

      

But even after you fix this, you will get a runtime exception because behind the scenes, the classes you declare in your sketch are the inner classes of your sketch class. You cannot use reflection in inner classes the way you are trying.

So you either need to change the way these classes are declared, or you need to change the way they are reflected.

To make sure that processing does not turn these classes into inner classes of your sketch, you must define them in your .java tabs . Use the class name followed by .java , so Processing knows that it is a Java class, not a "processing class" that is being converted to an inner class. Your installation will look like this:



screenshot of pde

With this approach, you would need to pass an instance of your sketch to the java classes in order to access any of the processing methods. Instead, you can simply change how you make your reflection. Since the classes are the inner classes of your sketch class, you need to go through the sketch class to get to them:

void setup() {
  try {

    Class<?> sketchClass = Class.forName("sketch_150702a");
    Class<?> innerClass = Class.forName("sketch_150702a$Wtf");

    java.lang.reflect.Constructor constructor = innerClass.getDeclaredConstructor(sketchClass);

    IMenuRunnable u = (IMenuRunnable)constructor.newInstance(this);
    println(u.toString());
  }
  catch(Exception e) {
    e.printStackTrace();
  }
}

interface IMenuRunnable {
}

public class Wtf implements IMenuRunnable { 
  public Wtf() {
  }
}

      

Alternatively, you can simply declare your Wtf

class to be static:

void setup() {
  try {
    Class<Wtf> c = Wtf.class;
    IMenuRunnable u = (IMenuRunnable) c.newInstance();
    println(u.toString());
  }
  catch(Exception e) {
    e.printStackTrace();
  }
}

interface IMenuRunnable {}

static public class Wtf implements IMenuRunnable{ 
  public Wtf() {
  }
}

      

Of course, then you won't be able to access the non-stationary members of your sketch class, so the approach you take really depends on what you need to do.

+1


source







All Articles