Approach doing the same stuff on different objects - java

I am currently making a library which is an utility for me to handle something which is not associated with the question (I am implicitly not saying the subject because it is not really important), however it does use reflection.
I am retrieving all declared and inherited methods from a class, which currently works fine and is not the issue. But the thing is, I need to do this as well for sub-classes since those inherit over like methods do (however you cannot override those like methods).
The problem that I am facing that it will use the same algorithm but there will be on difference, instead of calling clazz.getDeclaredMethods() I need to call clazz.getMethods. What is the best way too approach this, and I kind of need to return Class[] and Method[] in the method signature as well.
Normally I would look for a shared superclass, but in this case I prefer to the have Class[] and Method[] accordingly. For starters, I did some research and found some shared superclasses:
GenericDeclaration
AnnotatedElement
Since I need both Class[] and Method[] arrays I am thinking something
like generics, so the method would look like:
public static <T extends GenericDecleration> T[] getT () {
}
As mentioned by dasblinkenlight this will not work since the method doesn't take any arguments and cannot check whether to retrieve Class or Method objects.
But how would I detect whether I need to call getDeclaredMethods or getDeclaredClasses?
What is the best approach on how to do this without duplicating a lot of code? I really tried to explain myself here, but if it is still unclear what I am doing please feel free to ask away!
Thank you very much in advance!
After messing around with this, I have found a solution that totally fits my needs. This is a combination of generics and #dasblinkenlight's solution, like so:
public interface DeclExtractor<T extends GenericDecleration> {
public T[] extract (Class clazz);
public Class<? extends T[]) getGenericClass ();
DeclExtractor<Method> methodExtractor = new DeclExtractor<Method>() {
#Override
public Method[] extract (Class clazz) {
return clazz.getDeclaredMethods();
}
#Override
public Class<? extends Method[]> getGenericClass () {
return Method[].class;
}
}
// Same for Class
}
Now the method which also will return the correct type so you dont have to manually cast all GenericDeclaration to your original object type. My issue was that I used a collection for it and not the correct array:
public <T> T[] getAll (final DeclExtractor<T> extractor, Class<?> clazz) {
T[] declaration = extractor.extract (clazz);
//.. The algorithm..
// Return an instance of a collection as array (I use a set in my implementation)
final Object[] objects = myCollection.toArray();
return Arrays.copyOf(objects, objects.length, extractor.getGenericClass());
}
Technically you do not need the getGenericClass method in the interface, but I am using extract directly in a loop so I cannot pull the class of that, however, you can.
Hopefully this helps someone in the future :) Thanks again to #dasblinkenlight for the inspiration!

Your getT needs to get some input in order to decide what to do.
What about a method which can takes an enum as argument to determine whether it needs to get classes or methods? (from a comment)
There is a better approach: define an interface that performs the appropriate extraction, and make two instances of it - one for extracting classes, and one for extracting methods:
public interface DeclExtractor {
GenericDecleration[] extract(Class cl);
final DeclExtractor forClasses = new DeclExtractor() {
public GenericDecleration[] extract(Class cl) {
// make an array of GenericDecleration from extracted classes
}
};
final DeclExtractor forMethods = new DeclExtractor() {
public GenericDecleration[] extract(Class cl) {
// make an array of GenericDecleration from extracted methods
}
};
}
Now you can rewrite your getT to take an "extractor", like this:
public static GenericDecleration[] getT (DeclExtractor extractor, Class cl) {
...
// When it's time to get components of the class, make this call:
GenericDecleration[] components = extractor.extract(cl);
...
}
To initiate a call to getT, pass DeclExtractor.forClasses or DeclExtractor.forMethods:
GenericDecleration[] c = getT(DeclExtractor.forClasses);
GenericDecleration[] m = getT(DeclExtractor.forMethods);

Related

Class registration using reflection

I'm learning about Factory Pattern and I am using THIS article as a source. In it, there is this piece of code:
class ProductFactory {
private HashMap m_RegisteredProducts = new HashMap();
public void registerProduct (String productID, Class productClass) {
m_RegisteredProducts.put(productID, productClass);
}
public Product createProduct(String productID) {
Class productClass = (Class)m_RegisteredProducts.get(productID);
Constructor productConstructor = cClass.getDeclaredConstructor(new Class[] { String.class });
return (Product)productConstructor.newInstance(new Object[] { });
}
}
I'm having a hard time figuring out how createProduct() method works. When I'm trying to use this code I get Non-static method `getDeclaredConstructor(java.lang.Class<?>...)' cannot be referenced from a static context error. productClass variable is declared but never used so there is clearly something wrong with the code but I can't figure what exactly. I checked similar questions on SO but don't know how to repurpose them for this case. Reflection is a really confusing subject for me.
My questions:
What is wrong with this code?
Why it is passing new Class[] { String.class } in getDeclaredConstrutor() method and what does it mean?
Why is it passing Object array in newInstance() instead of just single object?
Question 1
There are several things wrong about this code.
It just does not compile because cClass member is missing. Logically, It should be productClass.getDeclaredConstructor instead.
Raw HashMap is used instead of generically typed Map<String, Class<? extends Product>>. Also raw typing for Class and Constructor.
The naming m_RegisteredProducts does not respect Java naming conventions.
Question 2
new Class[] { String.class } arg aims to retrieve the constructor with a single String arg, for example public Product(String id).
It could have been retrieved with just
productClass.getDeclaredConstructor(String.class);
because it is not mandatory to create arrays for varargs.
Question 3
This array arg just looks like a blunder. The constructor instance is retrieved for one with String arg, but it is passing something else to instantiate it. So inevitably there will be an exception thrown.
Conclusion
There are too many wrong or inaccurate things in this example and probably in the article itself. I'd recommend choosing another one.

Is it possible to define a method that accepts any number of nested lists?

I have no particular use for this in mind, but is it possible to write a method that accepts any number of nested lists in Java?
I got as far as this:
private <T extends List<? extends T>> void masterOfLists(final T list) {
}
The small issue with this now is that it never ends. I neither want to lose generics, so simply accepting an Object and try casting it to a List every pass is not an option in my question.
I hoped it would be clear enough, but appereantly it isn't for some, I want the method masterOfLists to accept the following examples (and way more):
masterOfLists(new ArrayList<Object>())
masterOfLists(new ArrayList<List<Object>>())
masterOfLists(new ArrayList<List<List<Object>>>())
masterOfLists(new ArrayList<List<List<List<Object>>>>())
Instead of Object it may also be a concrete type like String.
The used List may be any type of list, like ArrayList or LinkedList or your custom implementation.
Using pure List won't help you here, you need to define a recursive class.
As an additional source of inspiration you can take a look at my code for Recursive Tic-Tac-Toe
You could create a class something like this:
public class Recursive<T> {
List<Recursive<T>> sub;
T value;
boolean hasSub() {
return sub != null;
}
T getValue() {
return value;
}
void forEach(Consumer<T> t) {
if (hasSub())
sub.forEach(t);
else t.accept(value);
}
}
You can use logic in this class to prevent it from both having a sub-list and an actual value, using constructors and/or setters.
And then if you want to iterate over it and print out all the sub-items recursively, you can use
Recursive<T> recursive;
recursive.forEach(System.out::println);
Then your method can look like this:
private <T> void masterOfLists(final Recursive<T> list) {
You won't get anywhere using pure Lists because the generic type of the list is not available at runtime, and the generics will only create a mess for you here. Using a recursive class is much easier.
The 'cheap' solution is to extend the ArrayList class with your own name, and force the Generics on the subclass. The SubClass is still an ArrayList....:
public class NestingList extends ArrayList<NestingList> {
// all we do is set the Generics...
}

new <T> in Java

I have this problem
a method which is cutting unwanted details from one class and returning collection of objects with wanted ones. the matter is I want this metod to be able to work with different classes ( which are based on one abstract, though), so I use generic type. the problem is that in one point I need to create an instance of , which is impossible. I looked for some way out, but it doesn't seem to work for my case.
So, code is following
private <T extends RestMandate> List<T> toRestMandate(List<CardMandate> mandates ) {
List<T> restMandates = new ArrayList<>(mandates == null ? 0
: mandates.size());
if (mandates != null) {
for (CardMandate mandate : mandates) {
restMandates.add(new T(mandate));
}
}
return restMandates;
}
RestMandate is base class, CardMandate were I take the info. Any ideas?
Since the generic type arguments are erased at runtime, there is no way you can refer to it like you are trying to do. The only way out is a type tag argument + reflective instantiation.
A better choice is to redesign your solution to solve this without relying on generics and type tags. Leverage dynamic method dispatch instead: add a method to RestMandate which will return the object converted to the desired type.
Because of Type Erasure, T becomes Object at runtime. You don't know its real type anymore.
You can still instantiate the object by reflection if you have its class. In order to do that, you must give the class to your method:
private <T extends RestMandate> List<T> toRestMandate(List<CardMandate> mandates, Class<T> clazz ) {
...
for (CardMandate mandate : mandates) {
/*
* I get the constructor which needs one CardMandate and call it.
* Note : I do not recommend this solution (no check at compile-time!).
* Like Marko Topolnik, I advise to redesign the solution.
*/
restMandates.add(clazz.getConstructor(CardMandate.class).newInstance(mandate));
}
...
}
To create an instance you require Class<T> object too
private <T extends RestMandate> List<T> toRestMandate(List<CardMandate> mandates, Class<T> clazz) {
//....
T newInst = clazz.newInstance();
//....
}

Generics without collection

I have a method that usually takes an item from a list and has a signature of:
myMethod(T item)
I want to use this method but I know what I am sending the method.
SpecificItem myItem = new SpecificItem();
myMethod((T) myItem);
This doesn't sit well with me. Is this a sign of bad code?
myMethod is defined in a generic class, somewhat like:
public class MyClass<T> {
T myItem;
public void myMethod(T item) {
// do Something with item
}
public T myOtherMethod() {
myMethod(myItem); // casting is not necessary
return myItem;
}
}
If you instantiate this class, you exchange the variable type T with a real one:
MyClass<SpecificItem > concreteClass = new MyClass<SpecificItem >();
And if you call myMethod on this instance, you have to provide a SpecificItem, because SpecificItem is the generic type for this instance.
(I'm not sure it my post answers your question, please comment so I can improve it)
It's better that you code to interface. For example :
In myMethod :
<T extends <? super Item>> void (T item);
This tells compiler to only accepts a generic type of T which is an implementation/extention of Item interface/class. This will make sure that given input is in correct type. Compiler guarantees it.
In main class :
Item myItem = new SpecificItem();
Code given above is the best practice. Get used to it. But (i discourage this) you can code like this too :
SpecificItem myItem = new SpecificItem();
You can read Java source code. For example in class java.util.Collections. In method sort(List) you may notice that Joshua Bloch makes sure that given input is always in correct format. To give it a try, do this :
public class Class1 {
public static void main(String[] args) {
List<Class1> list = new ArrayList<Class1>();
Collections.sort(list);
}
}
Above code will produce compilation error. To fix this compilation error Class1 must implement interface Comparable. This maintains the precondition of method sort(List) which assumes that given input is a List of Comparable.
Oh i almost forget about your question. Actually it's not a bad code since it works. I just want to tell you that there is a better way to do that.
You might be looking for something like this:
class C<? extends T> {
public void myMethod(T myItem) {
...
}
}
The way you call the method looks strange. If you have declared your generic method as
public <T> void myMethod(T item);
the compiler knows, that T is some abstract type and you shouldn't need to cast an input parameter to it. Just make sure, that T is not declared as some specific type in your code.
upd: look here for an example: http://www.java2s.com/Tutorial/Java/0200__Generics/Usinggenericmethodstoprintarrayofdifferenttypes.htm
Probably better way would be to make SpecificItem a subclass of T or make T an interface and have SpecificItem implement it.

How to by-pass inheritance in java when invoking a method

class Super {
public void anotherMethod(String s) {
retValue(s)
}
public String retValue(String s) {
return "Super " + s;
}
}
class Sub extends Super {
public void anotherMethod(String s) {
retValue(s)
}
public String retValue(String s) {
return "Sub " + s;
}
}
if suppose in main,
Super s = new Sub();
s.anotherMethod("Test");
Output will be, Sub Test
Can you anyone help me in telling how to get output Super Test with the given sequences in main.
And let me explain why I want this, say I have a class which has method test() and it can be overriden by sub classes, in some cases I want the overriden test() and in some cases I want the test() of super class itself, there are many ways to do this, best suggestions will be helpful.
Why would you ever want to do that ??
The whole point of polymorphism is to call the right method without the need to know which kind of instance you've got ...
Whenever I find myself asking (or being asked) a question like this, I know, categorically, that I have made a mistake in my design and/or my object definitions. Go back to your object hierarchy and check, double-check and triple-check that every inheritance relationship represents an "IS-A", and not a "HAS-A" or something even weaker.
And let me explain why I want this,
say I have a class which has method
test() and it's can be overriden by
sub classes, some cases I want the
overriden test() and in some cases
test() of super class itself, there
are many ways to do this, it will be
helpful if anyone can be best
solution.
If your subclass overrides test(), then it overrides test() - this is the whole point of object inheritance. You just call methods on the object, which are dynamically resolved to the appropriate implementation based on the object's runtime class. That's the beauty of polymorphic typing, in fact, the caller doesn't have to know about any of this at all, and the subclasses determine how their behaviour differs from the superclass.
If you sometimes want it to act as its superclass method and sometimes want it to act as its subclass method, then you need to provide the context required to do this. You could either define two test-type methods; one which is never overridden and so always returns the superclass' behaviour (you can even mark the definition with final to ensure it's not overridden), and your normal one which is overridden as appropriate by the subclasses.
Alternatively, if there is some contextual information available, you can let the subclasses decide how to handle this; their implementation(s) could check some proeprty, for example, and based on that decide whether to call super.test() or proceed with their own overridden implementation.
Which one you choose depends on conceptually whether your main method (i.e. the caller), or the (sub)class objects themselves, are going to be in the best position to judge whether the superclass' method should be called or not.
But in no case can you override a method and expect it to magically sometimes not be overridden.
You would have to go the route of:
Super s = new Super();
s.anotherMethod("Test");
...but that will defeat the purpose of inheritance if you also need whatever Sub's got. You could hack it like below but this seems an unelegant way to do it.
class Sub extends Super {
public String anotherMethod( String s, boolean bSuper ) {
if( bSuper )
return super.retValue(s);
else
return retValue(s);
}
public String retValue(String s) {
return "Sub " + s;
}
}
From class Sub you can call super.anotherMethod("bla"), but you cannot access the method of the superclass in your main method - that would be against the whole idea of using subclasses.
The runtime type of s is Sub, so you're only ever calling methods on that class.
Whilst I agree with the other posters that this is not the best idea in the world, I believe it could be done with a little bit of tinkering.
If your child class was defined as:
class Sub extends Super {
public void anotherMethod(String s) {
retValue(s)
}
public void yetAnotherMethodString s) {
super.retValue(s)
}
public String retValue(String s) {
return "Sub " + s;
}
}
and then call this new method in your main you would be able to print out "Super Test".
Doesn't seem like a very good plan tho. If you want access to parent functionality from a child class then don't override your parent method, just write a new one!
I'm hesistant to post this as an answer, since the question is quite horrible - but static methods would do roughly what the OP seems to want. Specifically, they are resolved on the compile-time declared class of the variable, not on the class of the instance held within that variable at runtime.
So modifying the original example:
class Super {
public static void staticMethod(String s) {
System.out.println("Super " + s);
}
}
class Sub extends Super {
public static void staticMethod(String s) {
System.out.println("Sub " + s);
}
}
public static void main(String[] args) {
Super s = new Sub();
s.staticMethod("Test");
}
then main() will print out "Super test".
But still don't do this until you understand why you want to, and you recognise that you are introducing subclasses and then gratuitously working around the point of them being there. Most IDEs for example will flag the above example with lots of warnings, saying that you shouldn't call static methods on instance variables (i.e. prefer Super.staticMethod("Test") instead of s.staticMethod("Test")), for exactly this reason.
You cannot modify Sub or Super directly? If you could control what instance of Sub is used you could do something like:
Super sub = new Sub() {
#Override
public String retValue() {
// re-implement Super.retValue()
}
};
otherObject.use(sub);
Of course this requires you to have or be able to reproduce the source code of Super.retValue() and for this method not to use anything you can't access from an anonymous child. If the API is this badly designed though, you might do well to think about changing it out for something else.
Can you anyone help me in telling how
to get output "Super Test" with the
given sequences in main.
Don't overwrite anotherMethod() and retValue() in Sub in the first place.
In Sub.anotherMethod(), return super.retValue(s) instead of retValue(s).

Categories

Resources