Before I describe my problem let my say that I suspect I might simply lack the correct terms to search for, and that's why my searches here on stackoverflor haven't been fruitful. So links to answers would also be very much appreciated.
Im trying to make a library that has a Factory, lets call it "MyFactory". MyFactory has a method that returns objects of the abstract class "MySuper", but also one that exposes the avilable subclasses to "MySuper". The library is intended to be expanded on a lot, so subclasses of "MySuper" will be added often, and then library will be recompiled, and dumped into a library folder of the application that uses it.
What I want is to be able to add a subclass of "MySuper" to the library, and have "MyFactory" become aware of it, preferebly without having to do anything else than create a new sublass of "MySuper"..
So far I use reflection to make "MyFactory" create new instances of a "MySuper" type, by giving the class name to a method, like this:
public MySuper getSuperObject(String name) {
return (MySuper) Class.forName("my.package." + name).newInstance(); }
But how can I get the factory to expose alle the "MySuper" classes as f.x. a List of String, so the applications that use the library know what they can call? Can I iterate the content of a package?
I'm open for solutions, the most important part is that in the future it should be very hassle free to add new "MySuper" sub-classes..
Thanks :-)
UPDATE:
I just want to note that I have found a nice Java library that handles reflection in an easy way, and lets you search for subtypes of a specific class. So my problem can be solved with that library (I have tested it). Here is a link: http://code.google.com/p/reflections/
You are looking for a Generic Factory Pattern. Something like..
public static <T extends MySuper> T createDocument(Class<T> subClazz) throws InstantiationException, IllegalAccessException {
return subClazz.newInstance();
};
You may google for Generic Factory Pattern and you will find lots of examples.
The default class loader knows nothing about a class until it searches for it. It then looks in several places depending on the class path. If you depend on the class loader you will not be able to get the class into the list until it has already been asked for by name.
The most automatic solution may be to designate a location, such as a directory, for new classes extending MySuper. To construct the list of classes, look in that directory for class files, and use your favorite bytecode library to check them for classes that extend MySuper.
Another option is to have a configuration file that lists the extending class names.
I suggest creating an enum that contains the possible subclasses to MySuper. whenever you add a subclass add an entry in the enum for the same and then you can give that as an input to the getMySuperObject() method.
do comment if u think i have left something in this solution
Related
I have a class Main.java in which I need to instantiate a bunch of other classes say C1.java ... C50.java. I am not able to think of an elegant way to instantiate these 50 classes in Main class. If I simply put all instantiating code in one place it looks so crowded and ugly. Today I have 50 classes to instantiate, tomorrow this count can increase to 100, then this situation will get worse. Can you please suggest an elegant way of instantiating all these classes without making Main class crowded with instantiation code. I am not aware of any design pattern to do this.
I am thinking to create an array of classes that needs to be instantiated and use reflection to instantiate them.
The answer depends on what purpose the classes would serve. However, if you don't mind to end up with an unordered collection of instantiated classes, there is a way to go using Reflections library and I guess also a shorted one in the matter of lines of code:
// find out all the classes implementing MyInterface
Set<Class<? extends MyInterface>> subTypes = reflections.getSubTypesOf(MyInterface.class);
// iterate those classes and instntinate them
List<MyInterface> objects = new ArrayList<>();
for (Class<? extends MyInterface> clazz: subtypes) {
objects.add(clazz.newInstance());
}
In any case, the whole design should be rethough.
The recommended solution is to use the service loader architecture.
Instantiating all registered implementations of MyInterface can be done as simple as
for(MyInterface my: ServiceLoader.load(MyInterface.class)) {
/* do something with <my> */
}
To make this work, its not enough to just implement the interface, these implementations must be declared as service providers, either via an entry in META-INF/services/ of your jar file (as described in the linked class documentation) or via provides declaration within a Java module declaration when using Java 9 or newer.
The advantage of this is not only a higher performance, compared to searching the entire class path with a reflection library, it also ensures that the necessary access rights are established when using Java’s module system in the future.
See also Java 9’s version of the class documentation.
I have inherited a project that uses calls to an existing jar. The former programmer have had the fortune of obtaining a/the source code of the jar. However the construction is rather complex. I use an abstract class, say Size. In the source code I find an implementation of that class, say SizeProxy. It has an object of class SizeImplementation and any calls on Size.getInfo() will be implemented as a call to this.theSize.getInfo().
In short I have managed to find the actual implementation of getInfo that actually does anything interesting. I would love to make it possible to go from "my" code o_size.getInfo() and go directly to the "implementation" in SizeImplementation.getInfo. Right now I can't make Eclipse do that, possibly because the class names don't match. Please help!
This is in general not possible because an interface can have several implementations, and an abstract class (or any class) can be extended by many classes. Take this example
public void doSomething(boolean option){
List<String> someList;
if (option){
list=new ArrayList<>();
}else{
list=new LinkedList<>();
}
list.add("Where do I go");
}
Were you to attempt to go to the implementing source directly from list.add("Where do I go"); to the implementation of .add() where would you end up? ArrayList's or LinkedList's.
This is why you have to go via the interface or abstract class then choose your implemetation from there
I'm attempting to write a framework to handle an interface with an external library and its API. As part of that, I need to populate a header field that exists with the same name and type in each of many (70ish) possible message classes. Unfortunately, instead of having each message class derive from a common base class that would contain the header field, each one is entirely separate.
As as toy example:
public class A
{
public Header header;
public Integer aData;
}
public class B
{
public Header header;
public Long bData;
}
If they had designed them sanely where A and B derived from some base class containing the header, I could just do:
public boolean sendMessage(BaseType b)
{
b.header = populateHeader();
stuffNecessaryToSendMessage();
}
But as it stands, Object is the only common class. The various options I've thought of would be:
A separate method for each type. This would work, and be fast, but the code duplication would be depressingly wasteful.
I could subclass each of the types and have them implement a common Interface. While this would work, creating 70+ subclasses and then modifying the code to use them instead of the original messaging classes is a bridge too far.
Reflection. Workable, but I'd expect it to be too slow (performance is a concern here)
Given these, the separate method for each seems like my best bet, but I'd love to have a better option.
I'd suggest you the following. Create a set of interfaces you'd like to have. For example
public interface HeaderHolder {
public void setHeader(Header header);
public Header getHeader();
}
I'd like your classes to implement them, i.e you's like that your class B is defined as
class B implements HeaderHolder {...}
Unfortunately it is not. Now problem!
Create facade:
public class InterfaceWrapper {
public <T> T wrap(Object obj, Class<T> api) {...}
}
You can implement it at this phase using dynamic proxy. Yes, dynamic proxy uses reflection, but forget about this right now.
Once you are done you can use your InterfaceWrapper as following:
B b = new B();
new IntefaceWrapper().wrap(b, HeaderHolder.class).setHeader("my header");
As you can see now you can set headers to any class you want (if it has appropriate property). Once you are done you can check your performance. If and only if usage of reflection in dynamic proxy is a bottleneck change the implementation to code generation (e.g. based on custom annotation, package name etc). There are a lot of tools that can help you to do this or alternatively you can implement such logic yourself. The point is that you can always change implementation of IntefaceWrapper without changing other code.
But avoid premature optimization. Reflection works very efficiently these days. Sun/Oracle worked hard to achieve this. They for example create classes on the fly and cache them to make reflection faster. So probably taking in consideration the full flow the reflective call does not take too much time.
How about dynamically generating those 70+ subclasses in the build time of your project ? That way you won't need to maintain 70+ source files while keeping the benefits of the approach from your second bullet.
The only library I know of that can do this Dozer. It does use reflection, but the good news is that it'll be easier to test if it's slow than to write your own reflection code to discover that it's slow.
By default, dozer will call the same getter/setters on two objects even if they are completely different. You can configure it in much more complex ways though. For example, you can also tell it to access the fields directly. You can give it a custom converter to convert a Map to a List, things like that.
You can just take one populated instance, or perhaps even your own BaseType and say, dozer.map(baseType, SubType.class);
I have two classes in my Java project that are not 'related' to each other (one inherits from Thread, and one is a custom object. However, they both need to use the same function, which takes two String arguments and does soem file writing stuff. Where do I best put this function? Code duplication is ugly, but I also wouldn't want to create a whole new class just for this one function.
I have the feeling I am missing a very obvious way to do this here, but I can't think of an easy way.
[a function], which takes two String arguments and does soem file writing stuff
As others have suggested, you can place that function in a separate class, which both your existing classes could then access. Others have suggested calling the class Utility or something similar. I recommend not naming the class in that manner. My objections are twofold.
One would expect that all the code in your program was useful. That is, it had utility, so such a name conveys no information about the class.
It might be argued that Utility is a suitable name because the class is utilized by others. But in that case the name describes how the class is used, not what it does. Classes should be named by what they do, rather than how they are used, because how they are used can change without what they do changing. Consider that Java has a string class, which can be used to hold a name, a description or a text fragment. The class does things with a "string of characters"; it might or might not be used for a name, so string was a good name for it, but name was not.
So I'd suggest a different name for that class. Something that describes the kind of manipulation it does to the file, or describes the format of the file.
Create a Utility class and put all common utility methods in it.
Sounds like an ideal candidate for a FileUtils class that only has static functions. Take a look at SwingUtilities to see what I'm talking about.
You could make the function static in just one of the classes and then reference the static method in the other, assuming there aren't variables being used that require the object to have been instantiated already.
Alternatively, create another class to store all your static methods like that.
To answer the first part of your question - To the best of my knowledge it is impossible to have a function standalone in java; ergo - the function must go into a class.
The second part is more fun - A utility class is a good idea. A better idea may be to expand on what KitsuneYMG wrote; Let your class take responsibility for it's own reading/writing. Then delegate the read/write operation to the utility class. This allows your read/write to be manipulated independently of the rest of the file operations.
Just my 2c (+:
I'm writing a functionality where it would be helpful to get the classes inside a certain package of my program. Also, I only want the classes that subclass a certain class.
I need the classes in order to call static methods on them.
Is there an automatic way to do this? If so, is it slow?
In case I was not clear, what I want is something like this:
ArrayList<Class<? extends MySuperClass>> classes = ;
classes.add(MyClass.class);
classes.add(MyClass2.class);
Instead of having to call add for each class, I would like to automatically get that class list.
The number of classes is small, so I would not mind declaring them manually if the automatic trick would be slow - this app is for a mobile platform.
In either way, I would also like to know how to call the static method for each method in the ArrayList:
// error The method nameOfStaticMethod is undefined for the type Class<capture#2-of ? extends MySuperClass>
classes.get(0).nameOfStaticMethod ();
Thanks for your comments.
Java doesn't provide this ability. There is no introspection at the package level. The classes could be records in a database, or on the other side of a network connection. There's no requirement for them to be stored and organized so as to facilitate enumerating them by package.
You could make a custom class loader and API to provide a method of listing the class names.
I too would like to list all classes in a package but so far the methods of doing this is pretty bad:
Like JOTN suggested - needs file access - not if it is a jar
Listing a JAR entries - well, also needs the jar file
Quoting a older SO question:
It isn't possible to query a Package for it's Classes (or even its subpackages). http://forums.sun.com/thread.jspa?threadID=341935&start=0&tstart=0 contains a very good discussion about why this is problematic, as well as a handful of solutions to your problem.
Anyways, here is how you invoke static methods on the class:
Method m = Integer.class.getMethod("toString", Integer.TYPE);
System.out.println(m.invoke(null, 123));