• Post Reply Bookmark Topic Watch Topic
  • New Topic

instantiating classes dynamically  RSS feed

 
Magnus Gunnarsson
Greenhorn
Posts: 10
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hello, my name is magnus and i hope this question fits here


i got a package with lots of classes
here they are:
Cond extends Operator
Start extends Operator
Store extends Operator

at the moment i only got like.... 10, but there'll be like 50 of them, the problem i got is that each one of these classes needs to be able to be created dynamically into an objects, as im gonna have arrays with several hundreds of instances of these classes, my current solution is to have an interface and using lamda have a sort of "operatorFactory"

new OperatorFactory(() -> new Cond());
new OperatorFactory(() -> new Start());
new OperatorFactory(() -> new Story());


this works but is very .. annoying to make and tedious, not to mention the fact that.. what if i forgot a few, and yeah, you can already see the issue, so yeah, my question is.. is there any better way to solve this issue? thank you

i tried
static
{

}
blocks in each class, and placed the "operatorfactory" there, yet this didnt work because, i guess apperently the classloader only activates the static block when the class is initialised, but i want the class to initialise itself..

also, i tried reflection and while it works, but its very messy
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Magnus, I'm not sure, from what you wrote, why you need a factory as opposed to just calling new Store() (or whichever class's constructor you need for the instance at hand). As each of your classes extends Operator, each instance of any of those classes is also an instance of Operator. All of the references to those instances can be stored in an array of type Operator[].

Can you tell us a little more about what you're doing? Maybe post some code you're actually using or have tried to use? We'll see what we can do.
 
Magnus Gunnarsson
Greenhorn
Posts: 10
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thank you for your reply, basically what i wanna do is to create an array with instances from these classes, okay i'll try give a more precise example of what i want

i want to.. basically parse strings, into instances, lets say i got a string saying "cond start store"
this should be changed into a 3 length array with a instance of the class cond instance at index 0, instance of the class start at index 1 and so on, now.. i could do a HUGE switch statement.. or similarly, but that just feels really really.. messy?

its so difficult to explain properly on a forum, but yeah, the initial idea was to make this java project run diffrent codes based on each words of a string, sorta like a very basic programming language? so converting the string into an array with instances that can be ran in sequence is the idea i had

thank you in adcance

edited to fix a few mistakes in the explanation
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A switch statement might not be very elegant, Magnus, but you can hide it in a factory method and it will be easy to maintain. Instead of arrays, I'd recommend using the ArrayList class. Very easy to add things to it dynamically, and it can be treated as an array. Here's an example of how I might start it, though there are a number of imperfections in this example that would make it a bad candidate for production code:


C:/users/smiller/strings/txt contains your input:

cond start store

When I run the above code, my output looks like this:

run:
dynamic.Cond@5c647e05
dynamic.Start@33909752
dynamic.Store@55f96302
BUILD SUCCESSFUL (total time: 0 seconds)


So, you can see that, even though my ArrayList contains Operator objects, each instance is still the proper subclass, created according to your text file's instructions.

Does that help any?
 
Magnus Gunnarsson
Greenhorn
Posts: 10
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
wouldnt it be better to insert the classes into a hashmap and link string to the classes

but yeah, your solution would certainly work, however i came here hopping there'd be some more dynamic solution to do this? i did find this
Google Reflection Api

but the reflection api is big and slow

also, maybe anyone has an idea of how to rework this? for example, in the past i tried to do a very similar code but using enums instead



this did work very well, except the code got incredibly cluttered

further ideas would be highly appreciated
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Magnus Gunnarsson wrote:wouldnt it be better to insert the classes into a hashmap and link string to the classes


Well, "better" demands on which master one must serve. A hashmap would, as far as I know, have to be loaded at run-time, and you would have to store instances of objects with your factory methods (which, I think, is what you were originally proposing). The code to initialize the map would probably look a lot like a switch statement, so the difference to maintainability seems slight, to me.

Your enum code is pretty confusing, to me. Can you flesh it out to something that actually compiles? I'd like to understand it better.
 
Magnus Gunnarsson
Greenhorn
Posts: 10
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
yes, that was infact me first solution that i originally posted about

i'll try get a quick example of what i meant by the enum

output:
> test code

i made this very quickly and messy, but it should show the idea ^^
an extremly annoying thing with this is that autocomplete doesent work when coding anon innerclasses/lambda in enums, inside eclipse

edit: added some comments into the code
 
Tim Holloway
Saloon Keeper
Posts: 18789
74
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For a large number of classes, probably a Hash works better than a switch-construct. Something like this:

 
Magnus Gunnarsson
Greenhorn
Posts: 10
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hmm, thats a very good idea actually, but i wonder, whats the speed diffrence between
class.newInstance();
and
new OperatorClass();

because, in the end this is gonna require create problably several several thousands of instances
 
Ron McLeod
Bartender
Posts: 1602
232
Android Angular Framework Eclipse IDE Java Linux MySQL Database Redhat TypeScript
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you want to remove the burden having to maintain a descriptor/properties file for mapping the friendly name to the class name, you could also use annotations and reflection to discover the classes and populate the map automatically at run time. A downside of this approach is that there may be a big investment in learning how to use annotations and reflection if you are not already familiar the APIs.



 
Magnus Gunnarsson
Greenhorn
Posts: 10
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hmmm.. intresting idea, im already quite familiar with annotations, but.. how do you get all classes with the annotation?
 
Tim Holloway
Saloon Keeper
Posts: 18789
74
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Magnus Gunnarsson wrote:hmm, thats a very good idea actually, but i wonder, whats the speed diffrence between
class.newInstance();
and
new OperatorClass();

because, in the end this is gonna require create problably several several thousands of instances


Write a benchmark test and let us know.

I doubt it's significant, because as far as I know, operator "new" is a pretty direct invocation of newInstance(), but the only real test is real-world production usage. Plus, different JVMs/versions may show different results, so I'd be wary of premature optimization.
 
Tim Holloway
Saloon Keeper
Posts: 18789
74
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Some variations on Ron's suggestion include adopting a standard package scheme for all operator classes and scanning that package subtree the way that certain Spring components do. Or, what the heck just scan EVERY class and introspect for children of "parent". It's a fair amount of overhead, but you only have to do it at startup.
 
Magnus Gunnarsson
Greenhorn
Posts: 10
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hmm, intresting, i might have to go for newInstance, yeah

Tim Holloway wrote:Some variations on Ron's suggestion include adopting a standard package scheme for all operator classes and scanning that package subtree the way that certain Spring components do. Or, what the heck just scan EVERY class and introspect for children of "parent". It's a fair amount of overhead, but you only have to do it at startup.


hmm, and how would one go with scannning all classes, any good libraries?
 
Ron McLeod
Bartender
Posts: 1602
232
Android Angular Framework Eclipse IDE Java Linux MySQL Database Redhat TypeScript
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Magnus Gunnarsson wrote:... any good libraries?

Take a look at Reflections (jar here).
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim Holloway wrote:For a large number of classes, probably a Hash works better than a switch-construct. Something like this:



That is probably more elegant, but I think it does tend to confirm my earlier assertion: that the switch code and the map loading code look a lot alike. Unless one is an indentation-style purist (and those are very rare ), the switch code can be made to look very similar to the code above:


Now, I'd be curious to know more about this little gem, hidden in Tim's comments:



Loading the strings is trivial, but how do you load the classes from a list?
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Magnus Gunnarsson wrote:i'll try get a quick example of what i meant by the enum


Wow! If I understand this correctly, each initial reference made to one of the enumerated constants calls EnumTest's constructor, passing the constant's argument which, in your case, is an instance of an anonymous inner class that implements your functional interface, but in a way that can be unique to the constant.

That.

Is.

Cool.

You came here looking for help, but you taught me something new! Thanks, Magnus. Have a cow.
 
Ron McLeod
Bartender
Posts: 1602
232
Android Angular Framework Eclipse IDE Java Linux MySQL Database Redhat TypeScript
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:Loading the strings is trivial, but how do you load the classes from a list?

If the list contains Strings with the fully qualified class names, then you can simply do something like:
    Class<?> clazz = Class.forName(className);
 
Rob Spoor
Sheriff
Posts: 21131
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:which, in your case, is an instance of an anonymous inner class that implements your functional interface

Not an anonymous inner class but a lambda expression. The latter does not create a class file (no EnumTest$1.class).
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Spoor wrote:
Stevens Miller wrote:which, in your case, is an instance of an anonymous inner class that implements your functional interface

Not an anonymous inner class but a lambda expression. The latter does not create a class file (no EnumTest$1.class).

Isn't that a matter of the implementation? From the language's perspective, a lambda is the same as an instance of an anonymous inner class, isn't it?
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Magnus Gunnarsson wrote:i want to.. basically parse strings, into instances, lets say i got a string saying "cond start store"
this should be changed into a 3 length array with a instance of the class cond instance at index 0, instance of the class start at index 1 and so on, now.. i could do a HUGE switch statement.. or similarly, but that just feels really really.. messy?

The only worry I have about this is that you could really only ever access these subclasses as Operators - ie, they would be kind of like anonymous classes - but if that really is all you need then one thing that might help is that enums can implement interfaces, so all you really need is:and then, providing your names are correctly chosen, you could populate your Operator array with something like:or indeed execute the methods directly with:and you wouldn't need any of that fancy lambda stuff.

Of course, it kind of depends on how complex your Operator interface is; but from what you've shown us, it would appear to involve only one method.

HIH

Winston
 
Magnus Gunnarsson
Greenhorn
Posts: 10
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
yes the interface will have only really one method, one thing about enum is that doing it like that would.. make it very cluttered, i mean, imagine hundreds of enums, all implementing the interface
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Magnus Gunnarsson wrote:yes the interface will have only really one method, one thing about enum is that doing it like that would.. make it very cluttered, i mean, imagine hundreds of enums, all implementing the interface

Well something, somewhere's got to implement it. And I don't see a pile of rather arcane lambdas being any less "cluttered" than a pile of implementations, unless there's something intrinsic to the token itself that lends itself to a functional implementation.

The lambda implementation would seem to save you 3 or 4 lines per enum instance at the cost of a fair bit of readability, IMO - especially if the method is more than 1 line long.

Winston
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:The lambda implementation would seem to cost ... a fair bit of readability, IMO

That said, I'm still quite new to lambdas, so maybe I'm just not "seeing" the advantage.

For streams and stuff, I think they're great. But as an instance factory it seems a bit awkward to me.

Winston
 
Rob Spoor
Sheriff
Posts: 21131
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:
Rob Spoor wrote:
Stevens Miller wrote:which, in your case, is an instance of an anonymous inner class that implements your functional interface

Not an anonymous inner class but a lambda expression. The latter does not create a class file (no EnumTest$1.class).

Isn't that a matter of the implementation? From the language's perspective, a lambda is the same as an instance of an anonymous inner class, isn't it?

Perhaps similar, but not the same.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!