I have a superclass, and then several subclasses, like this:
public abstract class A {
public abstract int getValue();
}
public class B extends A {
public int getValue() {
return 1;
}
}
public class C extends A {
public int getValue() {
return 123;
}
}
public class D extends A {
public int getValue() {
return 15234;
}
}
There are about 100 or so subclasses. I also have a manager:
public class Manager {
public static ArrayList<A> list = new ArrayList<A>();
}
How can I "magically" add an instance of all subclasses of A to list without manually creating an instance of every single subclass and adding it to the list? Perhaps with using an Initialization Block?
EDIT
It's not important how I access list in Manager. I edited it to be static.
(2nd attempt - my first attempt was based on a misunderstanding of the Question.)
I'm assuming that what you want to do is build a (static) list that:
contains exactly one instance of each of the subclasses,
is created and populated ahead of time, and
doesn't involve code in each subclass creating / adding an instance of itself to the list.
Firstly, an instance initializer block won't do this. An instance initializer is run when you create an instance ... and something has to new the class (i.e. each of the subclasses) for this to happen.
I think the only viable approach is to write some hairy reflective code that:
iterates over all classes on the classpath,
loads each one using Class.forName(),
reflectively tests to see if the class is a subclass of A,
if it is, reflectively invokes the classes no-args constructor and adds the resulting instance to "the list".
This is (IMO) pretty hacky!! And it is going to be expensive ... unless you can limit the "package space" that needs to be searched for these subclasses.
Actually, this could be a problem that would be better solved using an enum ... especially if the subclasses don't have behavioural differences that require different method implementations. (For instance your getValue() method could just return a private variable ... that you initialize using a constructor.) See #Paul Bellora's answer.
(The thing that would prevent this from being applicable would be if there needed to be multiple instances of some of the subclasses. That's not possible with enums.)
Each class is going to represent a command.
Based on the description of your problem, it sounds like A could be an enum:
public enum A {
B(1) {
#Override
public void execute() {
//code and stuff
}
},
C(123) {
#Override
public void execute() {
//code and stuff
}
},
D(15234) {
#Override
public void execute() {
//code and stuff
}
};
private final int value;
private A(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public abstract void execute();
}
Now, there is exactly one instance of each command, and you can easily iterate commands with A.values().
Although it doesn't quite make sense... one way you can do is, do things similar to Spring's component scanning: make use of things like PathMatchingResourcePatternResolver and find out all possible classes. Iterate through them and add to list if that is a subclass of A.
This is a bit of a hackish way to do it, but if all your subclasses are in one folder (the actual class files) you could iterate over the files in the folder and use the ClassLoader. You code would look something along the lines of -
for(String className : classNames){
Class clazz = classLoader.loadClass(className);
list.add(clazz.newInstance());
}
Look at the ClassLoader API for more info. Also keep in mind that this is not very efficient, but if you are just doing this once you should be fine.
Could be like this :
public abstract class A {
public A(Manager m) {
m.list.add(this);
}
public abstract int getValue();
}
public class B extends A {
public B(Manager m) {
super(m);
}
}
This way you never again have to deal with m.list.add(new A()); while subclassing. But I don't know if this is what you are looking for...
EDIT :
It's not important how I access list in Manager. I edited it to be static.
If you don't care about using singletons, here is a very basic implementation:
But read What is bad about singletons.
public class Manager {
private static Manager instance = null;
protected Manager() {
// Exists only to defeat instantiation.
}
public static Manager getInstance() {
if(instance == null) {
instance = new Manager();
}
return instance;
}
}
Then:
public abstract class A {
public A() {
Manager.getInstance().list.add(this);
}
public abstract int getValue();
}
public class B extends A {
}
But, again this is very not satisfying as a design...
1) You need to find all available subclasses of class A. For that you need to scan all classes on the Java classpath. To make things easier we can assume that all subclasses are in the same location as A.class. A is supposed to be in a jar or in a folder. We can find out its actual location as
URL url = A.class.getProtectionDomain().getCodeSource().getLocation();
2) Lets assume that it is a folder, eg file:/D:/workspace1/x/target/classes/. Now we should walk thru all .class files in this folder and subfolders. We can use File.listFiles or Java 7 NIO2 for that. We have 2 options
a) load each class and check its superclass
Class cls = Class.forName();
if (cls.getSuperClass() == A.class) {
...
b) use javaassist framework http://www.javassist.org or similar to work with class file directly
DataInputStream ds = new DataInputStream(new BufferedInputStream(path));
ClassFile cf = new ClassFile(ds);
String superClass = cf.getSuperClass();
if (superClass.equals("A")) {
Class cls = Class.forName(cf.getName());
...
option b is loads only the classes you actually need, option a is simpler but it loads all classes in the folder
In both cases you create of an instance as
A a = (A) cls.newInstance();
assuming that all subclasses have no-arg constructor
How about using a class path scanner to automatically detect your target classes :
List<Class<?>> classes = CPScanner.scanClasses(new ClassFilter().packageName("com.foo.*").superClass(A.class));
Since you've got the target classes, you can easily initialize them by using newInstance method.
By the way use the maven dependency below to use the given snippet:
<dependency>
<groupId>net.sf.corn</groupId>
<artifactId>corn-cps</artifactId>
<version>1.1.1</version>
</dependency>
Cheers.
Related
I'm new to Java.
There is repeating code in multiple files in a project I'm working on.
Object types can be Thing1, Thing2, Thing3 etc.
So the code looks like:
if (Thing1.getStuff() instanceof String) {
myObj.setString("Hello");
} else {
myObj.setString("World");
}
I want to extend myObj with a class and method to handle this, as such:
public class myObj extends DoStuff {...}
--
class DoStuff {
public String doThis(*WHAT_TYPE_TO_USE* input) {
var String = input.myMethod(); // I need to call method.
return "String after some logic";
}
}
Which should allow me to run:
myObj.doThis("Something");
However, I can't specify input to be a specific type in the method as it could be Thing1, Thing2 etc. Also, Thing1 and Thing2 can't be dynamically imported, can they? How can I run myMethod (which exists in Thing1 and Thing2)?
Any advice is appreciated.
You need your Thing classes to implement a common interface such as
public interface Thing {
public String myMethod();
}
public class Thing1 implements Thing {
...
}
If they don't have a common supertype, then the two myMethod methods are unrelated. The fact that they have the same name is irrelevant to Java; they're distinct methods defined in distinct classes. You can access them with reflection shenanigans, but then you're giving up a lot of type safety (at that point, you would just take an Object and trust the user to provide a value of the correct type; it's ugly and messy and I don't recommend it).
If the classes in question are third-party classes (i.e. that you don't control) and don't implement a common interface, then you need the adapter pattern. Basically, you define a new class that does implement the interface and wraps an instance of the original.
public class Thing1Adapter implements Thing {
private Thing1 impl;
public Thing1Adapter(Thing1 impl) {
this.impl = impl;
}
#Override
public String myMethod() {
return this.impl.myMethod();
}
}
...
DoThis(new Thing1Adapter(myThing1));
I want to hide the specialization classes from the external classes of the same package.
Example:
package com.app.letter;
public interface LetterChange {
void change();
}
public class A implements LetterChange{
public void change(){..}
}
public class B implements LetterChange{
public void change(){..}
}
To instantiate these classes I use a factory....
package com.app.letter;
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
return doesNotMatter.isA() ? new A() : new B();
}
Note, all of them are in the same package and I DO NOT WANT to put the factory and the specialized classes in a sub package and change the specialization classes' constructors to default (package).
Following this example, I have a third class in the same package
package com.app.letter;
public class DoesNotMatterClass{
public void situations(){
LetterFactory.getInstance(null); // Legal
new A(); Illegal
new B(); Illegal
}
}
I want to provide the A or B only by the factory LetterFactory.getInstance(doesNotMatter) which is in the same package.
Make A and B private static classes of the factory:
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
return doesNotMatter.isA() ? new A() : new B();
}
private static class A implements LetterChange{
public void change(){..}
}
private static class B implements LetterChange{
public void change(){..}
}
}
Only the factory knows the existence of these classes and can instanciate them.
First of all, I see no reason to not allow to instantiate your classes directly. Usually, you do not care who instantiated the class, as long as you are sure it was instantiated correctly.
Therefore, I believe you have not one problem, but two:
Provide a way for anyone to correctly create both class A and class B manually, if required.
Provide a way to instantiate either A or B given some set of abstract parameters (your Factory solution).
As for the first part, the are 3 ways to instantiate classes of different complexity correctly:
A constructor, which has a list of all required parameters and dependencies. This can be used for simple cases pretty well.
A factory method. This can be used for more complex scenarios.
A factory class/a builder class. These are usually used for complex scenarios.
Now, whichever one you choose, by all logic it should be allowed to be public. The constructor/factory method/factory class will enforce your rules to create a proper valid instance of either A or B. And, as I mentioned before, there is no possible scenario when you should disallow creating a perfectly good and valid instance of a class.
Let's say you went with a builder class as the most complex solution. Here's how your code might look:
package com.app.letter.A;
public class A {
A() { //Package visibility, we don't want anyone to create an invalid A class
...
}
...
}
public class ABuilder {
public void validateAndSetSomeCriticalParam(Param param) {
...
}
public A build() {
A a = new A();
a.setSomeCriticalParam(param);
...
return a;
}
}
The builder should be designed in a thought in mind, that it could not in any way produce an invalid instance of A. This way, you can allow the builder to be the only way of instantiating A and not worrying about it, because all instances it creates are always valid. You can utilize proper API on the builder or Exceptions to reach this.
Also, the builder approach is the most complex one, for some simpler scenarios you might use a bunch of public static factory methods. However the idea should remain the same - the public factory methods should ensure that they produce only valid instances of A.
Same stuff for B class, in other package:
package com.app.letter.B;
public class B {
...
}
public class BBuilder {
...
}
Now for the factory. Basically same thing you had, but with builders:
package com.app.letter;
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
if (doesNotMatter.isA()) {
ABuilder builder = new ABuilder();
builder.setSomeCriticalParam(...);
builder...
return builder.build();
} else {
BBuilder builder = new BBuilder();
builder.setSomeBSpecificParam(...);
builder...
return builder.build();
}
}
}
And about the usages:
public class DoesNotMatterClass{
public void situations(){
LetterFactory.getInstance(..whatever..); // Legal
new A(); //Illegal, as it is package protected
new B(); //Illegal, as it is package protected
new ABuilder(); //Legal, as ABuilder can ensure that only valid As are created
new BBuilder(); //Legal, as BBuilder can ensure that only valid Bs are created
}
}
I will add, repeating myself once again, you should only hide the parts of your system that can be abused in some ways. There is no point of hiding a class or a method if there is no way for it to be abused. Therefore, if you provide a way to correctly initialize a valid instance of A or B it should not matter to you that some other part of the system can see it or use it.
You can hide A and B from other packages by making them package-protected.
But that won't hide them from classes in the same package.
Since they have to be visible by the factory, but not by any other class of the same package, the only way to do that is to make them private static nested classes of the factory class.
Static method M returns an object implementing interface A:
interface A { ... }
static A M() { ... }
Within M I would like to construct an object of type B and return that, given that B implements A:
class B implements A { ... }
I do not want client code to know anything about how B is implemented, I would prefer for B not to be a static class, B must be immutable and there could be different B handed to different clients. I want to prevent instantiation of B outside method M at all costs (short of reflection, as one user commented).
How can I achieve the above? Where and how should I implement B? Could you please provide a short code example?
My main problem is: how can I have "different Bs?"
A static inner class is probably your best bet. You won't be able to "prevent instantiation of B at all costs" since with reflection, client code can bypass all access modifiers.
You can use anonymous inner class that won't be called B (is anonymous) but will implement A for example
interface A {
void someMethod();
}
public class Test {
static A M() {
return new A() {// it will create and return object of anonymous
// class that implements A
#Override
public void someMethod() {
}
};
}
}
Without using reflection object of anonymous class can be created only by method M. Also it can't be extended so it is good first step to immutability.
You could also use a Proxy implementation to hide the implementation class further
public interface A {
public Object getValue();
}
public class Factory {
public static A newInstance() {
return new ProxyA(AImpl);
}
}
public class ProxyA implements A {
private A proxy;
public ProxyA(A proxy) {
this.proxy = proxy;
}
public Object getValue() {
return proxy.getValue();
}
}
All this is really doing is hiding the implementation of A under another layout and makes it difficult to create a instance of ProxyA
But as #Asaph points out, with reflection, it becomes next to near impossible to truly guard against people accessing various parts of the classes and objects...
You could also separate your interface and implementations via different Classloaders, so that you only ever expose the interface's to the developers and implementations are delivered by dynamic class loading them at runtime. While not solving the underlying problem, it further complicates the matters for those trying to circumvent your factory.
IMHO
Given the following three classes how can I use reflection to call the initialize function for the parent class(es) and then the subclass:
public class Test {
public static void main(String[] args) {
ExtendedElement ee = new ExtendedElement();
initialize(ee);
}
public static void initialize(Element element) {
System.out.println(element.getClass());
initialize(element.getClass());
}
public static void initialize(Class clazz) {
System.out.println(clazz.getClass());
}
}
public class Element {
protected String value;
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
}
public class ExtendedElement extends Element {
protected String extendedValue;
public void setExtendedValue(String extendedValue) {
this.extendedValue = extendedValue;
}
public String getExtendedValue() { return extendedValue; }
}
I'm not quite sure on how to paramertize the initialize function in the Test class, as the clazz parameter is a raw type.
What I essentially need is to call initialize up the class hierarchy if what I pass into initialize is of a subclass of Element.
Something like the following:
public void initialize(Class clazz) {
if (Element.class.isInstance(clazz.getClass().getSuperclass()) {
initialize(clazz.getClass().getSuperclass());
}
//Work to call initialize function
}
Edit 1:
Can't I parameterize the above pseudo function differently to retain the type of the object and then call the function I need to?
What I'm trying to do is avoid having to have the same method overridden for each of my classes and allow some inheritance for my Selenium 2 Page Objects. What I need to do is be able to is introspect the superclass(es) of my self and initialize each of my WebElement fields prior to running tests on these fields.
These are being injected with spring, and to further complicate things I am allowing tests to be written using Spring Expression language. I am lazy loading my beans, and using the InitializingBean interface to attempt to initialize my WebElements prior to their usage to avoid NPEs.
I had to wrap the WebElements with a custom object so that I could inject the location strategies using spring (We reuse a lot of pieces, but they have different ids / class names dependent upon where they are used in the application; this was done prior to me getting here and will not be changed at this time despite my arguments for consistency). For example we have a date widget that has different granularities, sometimes we need just a month, sometimes month and year, etc... It'd be nice if I could use an abstract class and break these commonalities down to their least common denominator and extend from there. To do that I need to be able to do the following in my base class:
public abstract class PageObject implements InitializingBean {
...
public void afterPropertiesSet() {
//Pass in concrete impl we are working with - this allows me to initialize properly
initializeWebElements(this.getClass());
}
...
public void initializeWebElements(Class clazz) {
//This does not grab inherited fields, which also need to be initialized
for (Field field : clazz.getDeclaredFields()) {
if (WidgetElement.class == field.getType()) {
Method getWidgetElement = clazz.getDeclaredMethod("get" +
StringUtils.capitalize(field.getName()), new Class [] {});
WidgetElement element =
(WidgetElement) getWidgetElement.invoke(this, new Object [] {});
element.initElement();
}
}
You can't call a method at a specific level. The only thing is you have access to the super keyword inside the class itself.
To make this work, you want to call super.initialize() from within each subclass, then just call it via reflection.
This is not C++, where you can call a specific method at a specific level of the inheritance hierarchy.
I'm not quite sure on how to parameterize the initialize function in the Test class, as the clazz parameter is a raw type.
Nothing in your example requires you to make use of the generic type parameter, so declare it as Class<?>.
I don't understand what your initialize methods are really trying to do, but there are a number of problems:
You seem to have one initialize method that takes an instance (of Element) as an argument, and another that takes a Class object as an argument. That's really apples and oranges stuff ... and you need to explain what you are trying to do.
Your attempt at fleshing out the method contains this:
Element.class.isInstance(clazz.getClass().getSuperclass())
This will never evaluate to true, because it is asking if some Class object is an instance of the Element class. (What is more, clazz.getClass().getSuperclass() is actually going to be the same as java.lang.Object.class. The class of a Class object is java.lang.Class and its superclass is java.lang.Object).
But I can't figure out what it should be, because you don't clearly describe what you are trying to achieve.
Here is my temporary solution, leaving question open to hopefully gather some better answers though for my use case.
public abstract class PageObject implements InitializingBean {
...
public void afterPropertiesSet() {
Class clazz = this.getClass();
do {
initializeElements(clazz);
clazz = clazz.getSuperclass();
} while (clazz != null);
}
What would be the practical side of the ability to define a class within an interface in Java:
interface IFoo
{
class Bar
{
void foobar ()
{
System.out.println("foobaring...");
}
}
}
I can think of another usage than those linked by Eric P: defining a default/no-op implementation of the interface.
./alex
interface IEmployee
{
void workHard ();
void procrastinate ();
class DefaultEmployee implements IEmployee
{
void workHard () { procrastinate(); };
void procrastinate () {};
}
}
Yet another sample — implementation of Null Object Pattern:
interface IFoo
{
void doFoo();
IFoo NULL_FOO = new NullFoo();
final class NullFoo implements IFoo
{
public void doFoo () {};
private NullFoo () {};
}
}
...
IFoo foo = IFoo.NULL_FOO;
...
bar.addFooListener (foo);
...
I think this page explains one example pretty well. You would use it to tightly bind a certain type to an interface.
Shamelessly ripped off from the above link:
interface employee{
class Role{
public String rolename;
public int roleId;
}
Role getRole();
// other methods
}
In the above interface you are binding the Role type strongly to the employee interface(employee.Role).
One use (for better or worse) would be as a workaround for the fact that Java doesn't support static methods in interfaces.
interface Foo {
int[] getData();
class _ {
static int sum(Foo foo) {
int sum = 0;
for(int i: foo.getData()) {
sum += i;
}
return sum;
}
}
}
Then you'd call it with:
int sum = Foo._.sum(myFoo);
I can say without hesitation that I've never done that. I can't think of a reason why you would either. Classes nested within classes? Sure, lots of reasons to do that. In those cases I tend to consider those inner classes to be an implementation detail. Obviously an interface has no implementation details.
One place this idiom is used heavily is in XMLBeans. The purpose of that project is to take an XML Schema and generate a set of Java classes that you can use bidirectionally to work with XML documents corresponding to the schema. So, it lets you parse XML into xml beans or create the xml beans and output to xml.
In general, most of the xml schema types are mapped to a Java interface. That interface has within it a Factory that is used to generate instances of that interface in the default implementation:
public interface Foo extends XmlObject {
public boolean getBar();
public boolean isSetBar();
public void setBar(boolean bar);
public static final SchemaType type = ...
public static final class Factory {
public static Foo newInstance() {
return (Foo)XmlBeans.getContextTypeLoader().newInstance(Foo.type, null);
}
// other factory and parsing methods
}
}
When I first encountered this it seemed wrong to bind all this implementation gunk into the interface definition. However, I actually grew to like it as it let everything get defined in terms of interfaces but have a uniform way to get instances of the interface (as opposed to having another external factory / builder class).
I picked it up for classes where this made sense (particularly those where I had a great deal of control over the interface/impls) and found it to be fairly clean.
I guess you could define a class that is used as the return type or parameter type for methods within the interface. Doesn't seem particularly useful. You might as well just define the class separately. The only possible advantage is that it declares the class as "belonging" to the interface in some sense.
Google Web Toolkit uses such classes to bind 'normal' interface to asynchronous call interface:
public interface LoginService extends RemoteService {
/**
* Utility/Convenience class.
* Use LoginService.App.getInstance() to access static instance of LoginServiceAsync
*/
class App {
public static synchronized LoginServiceAsync getInstance() {
...
}
}
}
With a static class inside an interface you have the possibility to shorten a common programming fragment: Checking if an object is an instance of an interface, and if so calling a method of this interface. Look at this example:
public interface Printable {
void print();
public static class Caller {
public static void print(Object mightBePrintable) {
if (mightBePrintable instanceof Printable) {
((Printable) mightBePrintable).print();
}
}
}
}
Now instead of doing this:
void genericPrintMethod(Object obj) {
if (obj instanceof Printable) {
((Printable) obj).print();
}
}
You can write:
void genericPrintMethod(Object obj) {
Printable.Caller.print(obj);
}
Doing this seems to have "Bad design decision" written all over it.
I would urge caution whenever it seems like a good idea to create a non-private nested class. You are almost certainly better off going straight for an outer class. But if you are going to create a public nested class, it doesn't seem any more strange to put it in an interface than a class. The abstractness of the outer class is not necessarily related to the abstractness of a nested class.
This approach can be used to define many classes in the same file. This has worked well for me in the past where I have many simple implementations of an interface. However, if I were to do this again, I would use an enum which implements an interface which would have been a more elegant solution.