• Post Reply Bookmark Topic Watch Topic
  • New Topic

Check if Class implements interface  RSS feed

 
Luigi Plinge
Ranch Hand
Posts: 441
IntelliJ IDE Scala Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm writing a GUI to launch the classes in a package that implement Runnable.

I have an array of Class objects, and some of the classes represented implement the Runnable interface.

1) How do I check to see if the Class in question implements Runnable?

2) If it does, how do I instantiate and run an object of that class?

Of course, the Class objects in the ArrayList don't themselves implement Runnable, but I want to find out about the classes they represent.

Code is something like



There is an isInstance method that can be used on a Class, but I don't think this is what I need since it takes an object as an argument and I don't see how this applies here.

I found someone with a similar problem here, but reading that thread I'm not much more enlightened (is the conclusion that you have to use BCEL?).
 
Stephan van Hulst
Saloon Keeper
Posts: 7969
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why do you have a list of Class? Why not just a list of Runnable?
 
Luigi Plinge
Ranch Hand
Posts: 441
IntelliJ IDE Scala Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've worked out how to run it, but not how to check if it's Runnable



 
Stephan van Hulst
Saloon Keeper
Posts: 7969
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You know about the instanceof operator, right?
 
Luigi Plinge
Ranch Hand
Posts: 441
IntelliJ IDE Scala Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:Why do you have a list of Class? Why not just a list of Runnable?


It's not a list of Runnables because I use a method (borrowed from here) to get the list of classes in the package.

I can't be sure that they all implement Runnable, so I want to check if they do. I can just create an instance and try casting it as above and catch an exception, but would be cleaner to check if it represents a Runnable first.
 
Matthew Brown
Bartender
Posts: 4568
9
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As Stephan mentions, there's the instanceof operator. You could use that to check the object you've created after you've created it (and before you've cast it to Runnable, obviously).

Or, if you want to check before you create the object, have a look at the isAssignableFrom method of Class.
 
Stephan van Hulst
Saloon Keeper
Posts: 7969
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm curious though, why would you want to do this? What is the purpose of your code?

Keep in mind that your code is very dangerous. Anyone could just drop a class file in that package and your code would run it and it would potentially wreak havoc.
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One other thing to consider - is there any chance that any of your classes don't have a no-arg constructor? If so you'll get an exception when you use Class.newInstance(), so you'll have to cope with that possibility.

[Edit: and what Stephan said ]
 
Luigi Plinge
Ranch Hand
Posts: 441
IntelliJ IDE Scala Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:You know about the instanceof operator, right?


I was thinking of testing before I instantiate the object, but I can't see how to do that.

Well, this works:
 
Stephan van Hulst
Saloon Keeper
Posts: 7969
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Luigi Plinge wrote:I was thinking of testing before I instantiate the object, but I can't see how to do that.

Matthew already provided the answer to this question.
 
Luigi Plinge
Ranch Hand
Posts: 441
IntelliJ IDE Scala Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:I'm curious though, why would you want to do this? What is the purpose of your code?

Keep in mind that your code is very dangerous. Anyone could just drop a class file in that package and your code would run it and it would potentially wreak havoc.


I'm just doing a bunch of the Project Euler exercises and each exercise solution has its own class. Just for my own benefit really, I just want to be able to kick off any solution from the project's Main class, automatically benchmarking the running time. Instead of having a ton of different public static void main(String[] args) methods, I just implement Runnable and kick the solution off in a run() method.
 
Luigi Plinge
Ranch Hand
Posts: 441
IntelliJ IDE Scala Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Matthew Brown wrote:One other thing to consider - is there any chance that any of your classes don't have a no-arg constructor? If so you'll get an exception when you use Class.newInstance(), so you'll have to cope with that possibility.

[Edit: and what Stephan said ]


Good point - well so far there is no chance, but I'll have to be careful how I write the constructor if there is one.

Which has got me thinking... what if I do want to pass in some arguments? I guess I could run a setParameters(...) method on the instance before running it.
 
Luigi Plinge
Ranch Hand
Posts: 441
IntelliJ IDE Scala Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Matthew Brown wrote:
Or, if you want to check before you create the object, have a look at the isAssignableFrom method of Class.


I do want to check before I create the object, but this method seems to be the wrong way round.

isAssignableFrom
public boolean isAssignableFrom(Class<?> cls)

Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter. It returns true if so; otherwise it returns false. If this Class object represents a primitive type, this method returns true if the specified Class parameter is exactly this Class object; otherwise it returns false.

Specifically, this method tests whether the type represented by the specified Class parameter can be converted to the type represented by this Class object via an identity conversion or via a widening reference conversion. See The Java Language Specification, sections 5.1.1 and 5.1.4 , for details.


It seems like I would need to run this method on a Runnable object and pass my Class in as an argument... I can't see how to do this.
 
Stephan van Hulst
Saloon Keeper
Posts: 7969
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, you need to pass your Class instances to the isAssignableFrom method.

However, isAssignableFrom is not a method in Runnable. So you don't need a Runnable instance. What kind of instance do you need?
 
Luigi Plinge
Ranch Hand
Posts: 441
IntelliJ IDE Scala Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:Yes, you need to pass your Class instances to the isAssignableFrom method.

However, isAssignableFrom is not a method in Runnable. So you don't need a Runnable instance. What kind of instance do you need?


isAssignableFrom needs to be run on the Class object that represents the Runnable interface.



Does this look right?
 
Stephan van Hulst
Saloon Keeper
Posts: 7969
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You got it.

I don't use Class enough to know whether you can use the simple name. If it complains, use Runnable's fully qualified name.
 
Luigi Plinge
Ranch Hand
Posts: 441
IntelliJ IDE Scala Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
w00t w00t, all working!

Thanks guys.



Runnable does need to be fully qualified.
 
Matthew Brown
Bartender
Posts: 4568
9
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That should work, but a class literal is better:
If you do want to pass parameters in: having a setParameters method is probably the easiest way, and is the way I'd do it. You could even define your own interface (extending Runnable) for all your classes to implement that contains the method. But Class.getConstructor/getConstructors give you a way to interrogate the class and call specific constructors if you really want to.
 
Luigi Plinge
Ranch Hand
Posts: 441
IntelliJ IDE Scala Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Matthew. Have changed to use the class literal (I was wondering what the .class thing was - now I know).

I think I'll quit while I'm ahead and not attempt the getConstructors thing, but nice to know it's there if I'm ever feeling brave.

Now you mention extending the interface, maybe a better way would be to make all my solution classes extend an abstract Solution class, and declare a setParameters method there that does nothing by default, which could be overridden as required... but this would be at the expense of flexibility, so maybe interfaces are the way to go. But I have something that works now, so I'm probably not refactoring unless I need to.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!