java.lang.NoSuchMethodException from a Class.forName instantiation

Hello all,

have been trying to debug this issue for hours with no luck,

I’m trying to instantiate classes using a csv file:

(I’ve also tried using getDeclaredConstructor)

*for this example, gun_name = "m4"*

Object new_gun = Class.forName(“gun_game_main$” + gun_name).getConstructor(arg_list).newInstance();

Sadly, I get this error:
java.lang.NoSuchMethodException: gun_game_main$m4.<_init>()

In my m4 class we can see that I have a default, no argument constructor:
class m4 extends gun
{
public m4()//String Sprite, float gunLength, game_manager GM)
{
println(“Instantiated m4”);
}
etc…

For some reason, I don’t get this error when I declare my m4 class as static?

This solution doesn’t work as I need to use a bunch of methods from non-static classes (random, loadImage, etc)

Any help would be greatly appreciated!

Thanks so much,
Rowan

The _init should just be init but since it’s wrapped in ‘<>’ it didn’t show up lol

Hmm,

this is not quite working for me - tried to adapt your solution to my code and as soon as I resolved the cast errors of Class<? extends PApplet>, I ended up with the same
java.lang.NoSuchMethodException: gun_game_main$m4.<_init>()

I also see that you’re getting the class by using an index of an array with the classes explicitly defined as opposed to using class.forName() which I’m attempting to use in my example.

Is there any way for Java to find my class constructor without having to make it static?

Really appreciate you taking the time to respond.

Hi @rowanmcnitt,

Would help to see your class structure but the issue is imho that you are trying to instanciate a nested class which constructor is internally not as it looks like, but rather nestedclass(Class Mainclass), even if you adding the default constructor…

ie: if you have such constuct …

public class Mainclass {
  public Mainclass() { }
  public class Nestedclass {
    public Nestedclass() {}
  }
}

the signatures sth like this:

constructors of Mainclass: public Mainclass()
constructors of Mainclass$Nestedclass: public Mainclass$Nestedclass(Mainclass)

you can check that depending on your code…

Class mycls = Class.forName("gun_game_main$" + gun_name);
Constructor[] constructors = mycls.getConstructors();
for(int i = 0; i < constructors.length; i++) {
   System.out.println("constructors of "+mycls.getName()+": " + constructors[i].toString());
}	

Cheers
— mnse

1 Like

The 3 classes (Dumb, Dumber, Dummy) in my example are both non-static & non-public.

So it’s very possible to find such classes as my example already demonstrates.

I’ve split up getDumb() into 2 functions in a separate tab:

  1. getSketchInnerClassConstructor() → returns a ClassConstructor.
  2. instantiateSketchInnerClass() → returns an instance from a Constructor.

Also made 2 functions to find nested classes:

  1. findAllSketchInnerClasses() → returns an array of all inner classes.
  2. findSketchNestedClassByName() → returns the nested class of a given name.

Here’s the whole sketch. Just ask again for further questions about it:

“Reflective_Inner_Class_Instantiation_Parameters.pde”:

/**
 * Inner Class Instantiation w/ Parameters (v1.0.1)
 * GoToLoop (2022/Jul/16)
 *
 * https://Discourse.Processing.org/t/
 * java-lang-nosuchmethodexception-from-a-class-forname-instantiation/37961/6
 */

static final String[] INNER_CLASS_NAMES = { "Dumb", "Dumber", "Dummy" };
static final int CLASSES = INNER_CLASS_NAMES.length;
static final Class<?>[] PARAM_TYPES = { String.class, int.class };

final Class<?>[] innerClasses = new Class<?>[CLASSES];
final Constructor<?>[] innerConstructors = new Constructor<?>[CLASSES];
final Dumb[] innerInstances = new Dumb[CLASSES];

void setup() {
  printArray(findAllSketchInnerClasses());
  println();

  for (int i = 0; i < CLASSES; ++i)  innerClasses[i] =
    findSketchNestedClassByName(INNER_CLASS_NAMES[i]);

  printArray(innerClasses);
  println();

  for (int i = 0; i < CLASSES; ++i)  innerConstructors[i] =
    getSketchInnerClassConstructor(innerClasses[i], PARAM_TYPES);

  printArray(innerConstructors);
  println();

  for (int i = 0; i < CLASSES; ++i)  innerInstances[i] =
    (Dumb) instantiateSketchInnerClass(innerConstructors[i], "abc", 50);

  printArray(innerInstances);
  exit();
}

class Dumb {
  String name;
  int age;

  Dumb(final String name, final int age) {
    this.name = name;
    this.age = age;
  }

  @Override String toString() {
    return getClass().getSimpleName() + ": " + name + ", " + age;
  }
}

class Dumber extends Dumb {
  Dumber(final String name, final int age) {
    super(name, age << 1);
  }
}

class Dummy extends Dumb {
  Dummy(final String name, final int age) {
    super(name, age >> 1);
  }
}

“Inner_Class_Reflective_Functions.pde”:

import java.util.List;
import static java.util.Arrays.asList;

import java.lang.reflect.Constructor;
import static java.lang.reflect.Modifier.isStatic;

final Class<?>[] findAllSketchInnerClasses() {
  final List<Class<?>> nested = new ArrayList<Class<?>>(
    asList(getClass().getDeclaredClasses()));

  int len = nested.size(), i = len;

  while (i-- > 0)  if (isStatic(nested.get(i).getModifiers())) {
    nested.set(i, nested.get(--len));
    nested.remove(len);
  }

  return nested.toArray(new Class<?>[len]);
}

final Class<?> findSketchNestedClassByName(final String name) {
  try {
    return Class.forName(getClass().getName() + '$' + name);
  }
  catch (final ClassNotFoundException ex) {
    System.err.println(ex);
    return null;
  }
}

@SafeVarargs final <T> Constructor<T> getSketchInnerClassConstructor(
  final Class<T> inner, final Class<?>... types)
{
  final Class<?>[] params = (Class[]) splice(types, getClass(), 0);

  try {
    return inner.getDeclaredConstructor(params);
  }
  catch (final NoSuchMethodException ex) {
    System.err.println(ex);
    return null;
  }
}

@SafeVarargs final <T> T instantiateSketchInnerClass(
  final Constructor<T> inner, final Object... args)
{
  final Object[] params = (Object[]) splice(args, this, 0);

  try {
    return inner.newInstance(params);
  }
  catch (final ReflectiveOperationException ex) {
    System.err.println(ex);
    return null;
  }
}