Java - Check for existence of method instead of NoSuchMethodException - java

In my code have a method that is supposed to invoke the method doSomething of an object. Upfront, it is not known if the object's class does have the public method or not. Until now, I used the following code:
try {
Method method = component.getClass().getMethod("doSomething", Boolean.TYPE);
method.invoke(component, true);
} catch (final NoSuchMethodException e) {
// do nothing as for some components the method "doSomething" simply does not exist
}
I now wonder if I should try to avoid the NoSuchMethodExceptionby checking if the object's class does have the public method doSomething.
final Method method = Arrays.stream(component.getClass().getMethods())
.filter(m -> m.getName().equals("doSomething")).findFirst().orElse(null);
if (method != null) {
method.invoke(component, true);
}
What do you think is better?

The real question is if the refection is really necessary here.
learning cool tricks and knowing reflection is awesome and important for a developer, and it help you understand a lot about. but its not always the right solution .
maybe you should just have in interface something like .
public interface DoingSometing {
SomeReturnObject doSomething(Boolean param);
}
and the component should implement the interface, and in worst case scenario, you will have to do casting to avoid reflection and you might fly on ClassCastException if the object that you have in your possession

Related

Java Generics AnyType, how do I allow any method to be called?

Given:
public<?> void methodName(? input){
var something = ?.GetItNow();
}
We have a ton of classes that were auto-generated from WSDL. Almost all of them have the same methods, but there is no way to have them implement an interface for those same methods. Assume all these different classes have a method named GetItNow(). My question is how do I set up a Generic method to allow the code above to work?
When using the "?" do I have to always use the "extends" key-word? If so how do I extend any object so I don't see compile errors that "method doesn't exist.
Note the code above is for illustration purposes only and does not do anything (yet).
You could use reflection to access the method, provided the name is known beforehand.
public void methodName(Object input){
try{
Method method = input.getClass().getMethod("GetItNow");
RETURN_TYPE returnValue = (RETURN_TYPE)method.invoke(input);
}catch(Exception e){
throw new RuntimeException("Error while invoking method",e);
}
}

Approach doing the same stuff on different objects

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);

Mockito - Mocking Concrete Classes

Given the following code:
LinkedList list = mock(LinkedList.class);
doCallRealMethod().when(list).clear();
list.clear();
by executing this test, a NullPointerException is thrown from first line in LinkedList#clear:
public void clear() {
Entry<E> e = header.next;
while (e != header) {
Entry<E> next = e.next;
//Code omitted.
but header has been instantiated before:
private transient Entry<E> header = new Entry<E>(null, null, null);
Could someone please explain what's happening during mock creation?
####### UPDATE. ######
Having read all answers especially Ajay's one, I looked into Objenesis source code and find out that it's using Reflection API to create the proxy instance (through CGLIB) and therefore bypassing all constructors in the hierarchy until java.lang.Object.
Here is the sample code to simulate the issue:
public class ReflectionConstructorTest {
#Test
public void testAgain() {
try {
//java.lang.Object default constructor
Constructor javaLangObjectConstructor = Object.class
.getConstructor((Class[]) null);
Constructor mungedConstructor = ReflectionFactory
.getReflectionFactory()
.newConstructorForSerialization(CustomClient.class, javaLangObjectConstructor);
mungedConstructor.setAccessible(true);
//Creates new client instance without calling its constructor
//Thus "name" is not initialized.
Object client = mungedConstructor.newInstance((Object[]) null);
//this will print "CustomClient"
System.out.println(client.getClass());
//this will print "CustomClient: null". name is null.
System.out.println(client.toString());
} catch(Exception e) {
e.printStackTrace();
}
}
}
class CustomClient {
private String name;
CustomClient() {
System.out.println(this.getClass().getSimpleName() + " - Constructor");
this.name = "My Name";
}
#Override
public String toString() {
return this.getClass().getSimpleName() + ": " + name;
}
}
You are only asking Mockito to call the real thing on clear, the underlying object is still a fake created by Mockito for you. If you need a real LinkedList then just use the LinkedList - only the most heated purist of BDD would tell you to mock everything around you. I mean, you are not mocking Strings are you?
Mockito author himself has said that calling the real thing should be used scarcely, usually only for testing a legacy code.
If you need to spy on the real object (track the invocations) then Mockito has a feature for this too:
List list = new LinkedList();
List spy = spy(list);
With spy, you can still stub a method if you need. It basically works like a mock, but isn't ;)
Your reasoning is flawless.
The key issue is that you are not operating on the actual LinkedList object. Here is what is happening behind the scenes:
The object that you are given by Mockito's mock() is an Enhancer object from the CGLIB library.
For me it is something like java.util.LinkedList$$EnhancerByMockitoWithCGLIB$$cae81a28
which kind of acts like a Proxy, albeit with the fields set to default values. (null,0 etc)
When you mock a class the object you are using is a fake, therefore the variables are not instantiated and the methods don't work as expected. You could use reflection to set a value for the header but I really wouldn't recommend this. As theadam said, the best thing to do would be to just use a list.

Java: how to specity a type for a function parameter without specifying a full type

Suppose i have a interface like this,
interface MyIntf{
void generate();
}
and a method like below
void run(Myintf x) {
x.generate();
}
I could call run() with an object of a class which implements MyIntf.
but is it possible in Java to declare run without an explicit name for the interface.
i.e. can i specify run() like this?
void run("Some object which has a method called 'void generate()'" x){
x.generate();
}
and run() can be called with an object of any class which has a method called
void generate();
You must then use reflection to do what you want. Something like:
void run(Object o) {
Method m = o.getClass().getMethod("generate", new Class[0]);
if (m!=null)
m.invoke(o, new Object[0]);
}
You must also add the necessary try/catch (which I don't know by heart), and I think you can pass null instead of the empty arrays.
Java uses "nominative" rather than "structural" typing.
Just because a method has the same name and parameters, doesn't mean it does the same thing (put the camera/gun to you head and shoot). If you need to make a legacy type conform to a particular interface, use an adapter. Avoid reflection.
No, you cannot do that. This is exactly what interfaces are for :)
Unless you don't use reflection..
You mean as if you would do something like this?:
void run(Object x) {
((Myintf)x).generate();
}
You could do:
void run(Object x){
try{
//use reflection to try and run a generate() method on x
} catch (Exception e){}
}
but there's no way to enforce that at compile time.
It is not possible to specify "some object which has a method called void generate()" in Java in the way that you have in mind.
In principle you could do this with reflection: you just pass in an Object and at runtime you check if there is a void generate() method that you can call. This means however that you are throwing away the type safety that the compiler provides; I don't recommend using this solution.
public void run(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Method m = obj.getClass().getMethod("generate");
m.invoke(obj);
}
The only way to do this in Java is to either use reflection or use the instanceof operator (which isn't recommended) and then cast the object being passed in to the correct class/interface.

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