1

I am passing a class as a parameter to a method and I need to create an instance of that class, something like

public void setPiece(int i0, int j0, Class<Piece> pieceClass) {
        Piece p = null;
        try {
            Constructor<pieceClass> constructor = new Constructor<>(argTypes);
            p = constructor.newInstance(args);
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        // other stuff
    }

but it won't accept this syntax. The argument inside <> needs to be a class, not a class object, so I don't know what to do.

I have seen people use something like pieceClass.newInstance(); which looks like might work, but it is deprecated and IntelliJ recommends that Constructor class. I'm more so just curious if it's possible to pass this parameter class as an argument for the generic, I haven't been able to find anything online.

  • Due to [type erasure (`oracle.com`)](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html), generic parameters are only available at compile-time. Thus, we cannot use class-instances as generic parameters. Neither can we use generic parameter to construct instaces of that type at runtime. – Turing85 Jan 04 '22 at 23:39
  • Why isn't `Constructor` what you want? – passer-by Jan 04 '22 at 23:46
  • 2
    Although you *could* do this with reflection, a better option is to pass the constructor itself as an argument: `public void setPiece(int i0, int j0, Supplier extends Piece> pieceConstructor)` An example invocation would be `setPiece(1, 5, SomePieceType::new);`. (But if you actually need to pass arguments to the constructors, it will be necessary to use an interface other than Supplier.) – VGR Jan 05 '22 at 00:25

1 Answers1

3

Ah, you've misread how to make Constructor instances. You can't new them up - you ask the Class for it. Looks like this:

try {
  Constructor<Piece> ctr = pieceClass.getConstructor(argTypes);
  p = constructor.newInstance(args);
} catch (InstantiationException | IllegalAccessException e) {
  throw new RuntimeException("uncaught", e);
}

NOTE: e.printStackTrace(); as sole line in a catch block is incredibly bad (the program continues running in a state that you clearly didnt expect and have no idea about. That's a really, really silly idea. Stop doing it, and fix your IDE so that it no longer fills this in for you. The catch block I wrote above is a fine default value for a catch block.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • **Further** - if you're fixing your IDE's default catch block, make sure you make it fill in the catch block with _something_, for example the line that rzwitserloot has given in this answer. An empty catch block is fractionally worse than a catch block that only has `e.printStackTrace();`. – Dawood ibn Kareem Jan 05 '22 at 01:02