Related
I am trying to write a java program where the user enters a testclass and then my program make sure it is a testclass. That is, checking for constructor without parameter, and testing the methods so that they are working (return true or false).
Now, what I am confused about is this API reflection. I am trying to follow the tutorial located at https://docs.oracle.com/javase/tutorial/reflect/index.html but I am getting confused and I am wondering if anyone could explain it and maybe help me get started. In the tutorial it says for example how to get the testclass, but you can do it in so many different ways. I tried using the
...
Class c = str.getClass();
...
where str is the name of the class I want to look at. How do I proceed from here to obtain information about the class's methods, constructor and their parameters? I simply just want examples and explaining. Not a fully written program. Thanks in advance.
Firstly, using Class c = str.getClass(); won't do what you want. It will return the class of the str object, which is just String. What you should do instead is use Class.forName(str); note that this will require the fully qualified name of the class.
Once you have the class object, you can use it's methods to get the relevant information. It sounds like the most useful to you would be .getConstructors(). With that, you could use (for example) the .getParameterCount() method of the Constructors to find any constructors which take no parameters. For more information, I'd advice looking at the documentation.
Retrieving class
Class.forName(str) will return the class with the given name. You must pass the fully qualified name, like "org.example.MyTestSuite". In other use cases where you want to create another instance of a given object, you can just call Object#getClass().
Constructors and Instantiation
You can get all constructor with Class#getConstructors(), so that you could check if a nullary constructor (without parameters) is available. Class#newInstance() will try to create an instance with the nullary constructor and throw an IllegalAccessException if none is available. Constructors with parameters can be invoked with Constructor#newInstance(Object...).
Methods
A class' methods will be listed with Class#getDeclaredMethods(). For further examination Method#getGenericParameterTypes() returns the parameters' classes. You can even make private methods invokable by using Method#setAccessible(true). Then finally Method#invoke(Class) executes the method on the given class instance. Use Method#invoke(Class, Object...) for methods with arguments, whereas the var-args represents the arguments.
Example
The Java Documentation contains some good examples, I modified one a little bit for your use case:
try {
// retrieving class
Class<?> c = Class.forName(str);
// will throw IllegalAccessException if the class
// or its nullary constructor is not accessible:
Object t = c.newInstance();
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods) {
String mname = m.getName();
// run only test methods
if (!mname.startsWith("test")) {
continue;
}
Type[] pType = m.getGenericParameterTypes();
if (pType.length != 0) {
throw new RuntimeException("Test methods must not have parameters.");
}
try {
// you can call private methods by setting this flag
m.setAccessible(true);
// invoking method m of instance t
m.invoke(t);
} catch (InvocationTargetException x) {
// Handle any exceptions thrown by method to be invoked.
Throwable cause = x.getCause();
err.format("invocation of %s failed: %s%n",
mname, cause.getMessage());
}
}
// production code should handle these exceptions more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
} catch (InstantiationException x) {
x.printStackTrace();
} catch (IllegalAccessException x) {
x.printStackTrace();
}
You can just invoke the appropriate methods from the Class class found Here. Namely, getDeclaredFields() and getDeclaredMethods()
I have this odd case which I'd like to handle through reflection or some library, if possible.
Is there a way to check if a class has a method and then invoke it on an already existing instance of the object?
For example, let's say I have:
Foo foo = new Foo();
Foo has a close() method. Let's say I know that a lot of the classes will have a close() method but since they were poorly devised and are legacy that I cannot re-write, I would like to find out a generic solution to invoke a method I know they all have, despite them not inheriting from a base class or interface.
I would like to have a method in my FooHandling class that accepts initialized objects and invokes their close() method. The objects will by no means inherit from the same base class, so they're totally different in nature, but all have a method with the same name. So, in FooHandler I'd like to have something like this:
void coolGenericClosingMethod(Object o)
{
// 1) Check via reflection if the class `o` represents contains a `close()`
// 2) Invoke the method, if it exists, but on the passed in object `o`.
}
So is there some neat trick I could use on an already instantiated object and still do that?
Is there a way to check if a class has a method
Class#getMethods()
Returns an array containing Method objects reflecting all the public member methods of the class or interface represented by this Class object, including those declared by the class or interface and those inherited from superclasses and superinterfaces
Class#getMethod(String,Class...)
Returns a Method object that reflects the specified public member method of the class or interface represented by this Class object. The name parameter is a String specifying the simple name of the desired method.
Throws:
NoSuchMethodException - if a matching method is not found
Sample code:
class Foo {
public void close() {
System.out.println("close method is invoked");
}
}
Foo foo = new Foo();
try {
Method m = Foo.class.getMethod("close");
m.invoke(foo);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
output:
close method is invoked
Yes you could use reflection for this, something like this would do it
public static Object invokeIfExists(Object obj, String methodName,
Class<?>[] argTypes, Object[] args) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Method method = null;
Object result = null;
try {
method = obj.getClass().getMethod(methodName, argTypes);
} catch(NoSuchMethodException | SecurityException e) {
// method not available in class or a security constrain has denied access
// ignore or at least do some loggin
}
if(method != null) {
result = method.invoke(obj, args);
}
return result;
}
The method to get the method object is Class#getMethod(String, Class...), it allows you to find the specific method you are looking for using it's signature (the formal parameter list) so among all overloaded methods you get exactly the one you need.
In all the exception thrown the one you might be the most interested in is InvocationTargetException which tells you that the method invoked has thrown an exception.
You could do what others have already answered, but there are some ready-made options if you do not want to mess too much with reflection. An example is Apache Commons BeanUtils:
import org.apache.commons.beanutils.MethodUtils;
...
try {
// 1st param: object reference
// 2nd param: method name
// 3rd param: args (null if no args)
MethodUtils.invoke(obj, "close", null);
} catch (NoSuchMethodException ex) {
// obj does not have a "close" method with no args
} catch (InvocatonTargetException ex) {
// obj.close() was called, and threw ex.getCause()
} catch (IllegalAccessException ex) {
// obj.close() exists, but you don't have permissions to invoke it
}
...
These libraries also tend to keep a method cache, so you get fast reflection; by caching you skip the slow part of reflection: method lookup.
This question already has answers here:
How to add test coverage to a private constructor?
(18 answers)
Closed 5 years ago.
If a class contains a bunch of static methods, in order to make sure no one by mistake initializes an instance of this class, I made a private constructor:
private Utils() {
}
Now .. how could this be tested, given that constructor can't be seen? Can this be test covered at all?
Using reflection, you can invoke a private constructor:
Constructor<Util> c = Utils.class.getDeclaredConstructor();
c.setAccessible(true);
Utils u = c.newInstance(); // Hello sailor
However, you can make even that not possible:
private Utils() {
throw new UnsupportedOperationException();
}
By throwing an exception in the constructor, you prevent all attempts.
I would make the class itself final too, just "because":
public final class Utils {
private Utils() {
throw new UnsupportedOperationException();
}
}
Test the intent of the code .. always :)
For example: If the point of the constructor being private is to not be seen then what you need to test is this fact and nothing else.
Use the reflection API to query for the constructors and validate that they have the private attribute set.
I would do something like this:
#Test()
public void testPrivateConstructors() {
final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
}
If you want to have a proper test for the object construction, you should test the public API which allows you to get the constructed object. That's the reason the said API should exist: to build the objects properly so you should test it for that :).
#Test
public//
void privateConstructorTest() throws Exception {
final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
// check that all constructors are 'private':
for (final Constructor<?> constructor : constructors) {
Assert.assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
// call the private constructor:
constructors[0].setAccessible(true);
constructors[0].newInstance((Object[]) null);
}
to make sure no one by mistake initializes an instance of this class
Usually what I do, is to change the method/constructor from private to default package visibility. And I use the same package for my test class, so from the test the method/constructor is accessible, even if it is not from outside.
To enforce the policy to not instantiate the class you can:
throw UnsupportedOperationException("don't instantiate this class!") from the default empty constructor.
declare the class abstract: if it only contains static methods, you can call the static methods but not instantiate it, unless you subclass it.
or apply both 1+2, you can still subclass and run the constructor if your test shares the same package as the target class.
This should be quite "error proof"; malicious coders will always find a workaround :)
If you have a private constructor, it is called from some not-so-private method of your code. So you test that method, and your constructor is covered. There's no religious virtue in having a test per method. You are looking for function or better yet branch coverage level, and you can get that simply by exercising the constructor through the code path that uses it.
If that code path is convoluted and hard to test, perhaps you need to refactor it.
If you add an exception in the constructor such as:
private Utils() {
throw new UnsupportedOperationException();
}
The invocation of constructor.newInstance() in the test class will throw an InvocationTargetException instead of your UnsupportedOperationException, but the desired exception will be contained in the thrown one.
If you want to assert the thrown of your exception, you could throw the target of the invocation exception, once the invocation exception has been caught.
For instance, using jUnit 4 you could do this:
#Test(expected = UnsupportedOperationException.class)
public void utilityClassTest() throws NoSuchMethodException, IllegalAccessException, InstantiationException {
final Constructor<Utils> constructor = Utils.class.getDeclaredConstructor();
constructor.setAccessible(true);
try {
constructor.newInstance();
} catch (InvocationTargetException e) {
throw (UnsupportedOperationException) e.getTargetException();
}
}
Don't. The constructor is private. That's all you need. Java enforces its privacy.
Don't test the platform.
I wish to initialize an array of java methods in the child class, as a class field like so
void callme() {System.out.println("hi!");}
Method[] actions = new Method[] {&callme,&callme};
and call all methods in this array at parent class like so:
for (meth:actions) {meth.invoke();}
However currently I cannot find a way to implicitly initialize the actions array, not through the constructor. The following gives me an error due to unhandled exception:
Method[] actions = new Method[] {
this.getClass().getDeclaredMethod("count")
};
As said, I cannot catch the exception when initializing this array explicitly as a field, and not in the constructor.
I'm a newbie to java reflection, so this is probably an obvious question, still I found no answer to that at google, any help would be appreciated.
Thanks
P.S.
As Scott below guessed, I "want a superclass to call a specific set of methods defined in a subclass".
Are you sure reflection is the right thing to do? Normally an interface with several anonymous classes implementing it would be better style.
You can write an initializer block to be able to catch the exception during initialization.
Why don't you use getMethod()?
[Note: code below has not been compiled but should get the idea across]
I should echo -- what are you trying to accomplish?
If you want a superclass to call a specific set of methods defined in a subclass, you can do a few things.
With reflection, I'd recommend using annotations:
1) define an annotation HeySuperclassCallMe (make sure retention is RUNTIME)
2) annotate the methods to call with HeySuperclassCallMe
#HeySuperclassCallMe public void foo...
3) in your superclass do something like
for (Method m : getClass().getMethods())
if (m.getAnnotation(HeySuperclassCallMe.class) != null)
m.invoke(...)
That's a nice reflective means to do it.
For non-reflection (which should be a bit faster, but more code):
1) define an interface that represents the calls
public interface Call {
void go();
}
2) in your superclass, define a
private List<Call> calls
protected void addCall(Call call)
3) in the subclass, use addCall:
addCall(new Call() {public void go() {foo();}} );
4) in the superclass
for (Call call : calls)
call.go();
Check out the Apache Commons - Beanutils! It's like a wrapper around all the reflection which is very easy to use. It wraps method invocation, modify attributes, lookups...
If you want to bring in dynamic to Java, you should have a look a dynamic JVM languages which can be used by simple including a .jar library! On of them is Groovy which contains the java syntax and bring in a lot of dynamic functionality (scripting, rapid-prototyping, Meta-Object-Protocol, runtime-method repacement, dynamic proxies...).
This should work as long, as your method is really declared in in the this.getClass().
If it is inherited, you should use Class.getMethod() instead.
However, instead of using function pointers, in java one would define an interface with a method one want to call, and let that interface be implemented by the target object.
Also consider using ArrayList, or other collection classes instead of arrays.
I can tell by your ampersands that you are thinking in C. We don't really use pointers to functions in java.
Generally, you would not use java reflection for this. As one of the other posters said - you would create an interface, and have objects that implemented that interface - either by directly implementing it, or with an adapter or anonymous class:
interface Callable { void callme(); }
Callable[] foo = new Callable[] {
new Callable() { public void callme() {System.out.println("foo!");}},
new Callable() { public void callme() {System.out.println("bar!");}}
};
for(Callable c: foo) {
c.callme();
}
Create a static method in your class which will return an array of declared methods and do the correct handling of exceptions.
private static Method[] declaredMethods(Class<T> clazz, String methodName) {
Method[] result = new Method[1];
try{
result[0] = clazz.getDeclaredMethod(methodName);
} catch (NoSuchMethodException nsme) {
// respond to the error
} catch (SecurityException se) {
// Respond to the error
}
return result;
}
Method[] actions = declaredMethods("count");
So, in Java, the first line of your constructor HAS to be a call to super... be it implicitly calling super(), or explicitly calling another constructor. What I want to know is, why can't I put a try block around that?
My specific case is that I have a mock class for a test. There is no default constructor, but I want one to make the tests simpler to read. I also want to wrap the exceptions thrown from the constructor into a RuntimeException.
So, what I want to do is effectively this:
public class MyClassMock extends MyClass {
public MyClassMock() {
try {
super(0);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// Mocked methods
}
But Java complains that super isn't the first statement.
My workaround:
public class MyClassMock extends MyClass {
public static MyClassMock construct() {
try {
return new MyClassMock();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public MyClassMock() throws Exception {
super(0);
}
// Mocked methods
}
Is this the best workaround? Why doesn't Java let me do the former?
My best guess as to the "why" is that Java doesn't want to let me have a constructed object in a potentially inconsistent state... however, in doing a mock, I don't care about that. It seems I should be able to do the above... or at least I know that the above is safe for my case... or seems as though it should be anyways.
I am overriding any methods I use from the tested class, so there is no risk that I am using uninitialized variables.
Unfortunately, compilers can't work on theoretical principles, and even though you may know that it is safe in your case, if they allowed it, it would have to be safe for all cases.
In other words, the compiler isn't stopping just you, it's stopping everyone, including all those that don't know that it is unsafe and needs special handling. There are probably other reasons for this as well, as all languages usually have ways to do unsafe things if one knows how to deal with them.
In C# .NET there are similar provisions, and the only way to declare a constructor that calls a base constructor is this:
public ClassName(...) : base(...)
in doing so, the base constructor will be called before the body of the constructor, and you cannot change this order.
It's done to prevent someone from creating a new SecurityManager object from untrusted code.
public class Evil : SecurityManager {
Evil()
{
try {
super();
} catch { Throwable t }
{
}
}
}
I know this is an old question, but I liked it, and as such, I decided to give it an answer of my own. Perhaps my understanding of why this cannot be done will contribute to the discussion and to future readers of your interesting question.
Let me start with an example of failing object construction.
Let's define a class A, such that:
class A {
private String a = "A";
public A() throws Exception {
throw new Exception();
}
}
Now, let's assume we would like to create an object of type A in a try...catch block.
A a = null;
try{
a = new A();
}catch(Exception e) {
//...
}
System.out.println(a);
Evidently, the output of this code will be: null.
Why Java does not return a partially constructed version of A? After all, by the point the constructor fails, the object's name field has already been initialized, right?
Well, Java can't return a partially constructed version of A because the object was not successfully built. The object is in a inconsistent state, and it is therefore discarded by Java. Your variable A is not even initialized, it is kept as null.
Now, as you know, to fully build a new object, all its super classes must be initialized first. If one of the super classes failed to execute, what would be the final state of the object? It is impossible to determine that.
Look at this more elaborate example
class A {
private final int a;
public A() throws Exception {
a = 10;
}
}
class B extends A {
private final int b;
public B() throws Exception {
methodThatThrowsException();
b = 20;
}
}
class C extends B {
public C() throws Exception { super(); }
}
When the constructor of C is invoked, if an exception occurs while initializing B, what would be the value of the final int variable b?
As such, the object C cannot be created, it is bogus, it is trash, it is not fully initialized.
For me, this explains why your code is illegal.
I can't presume to have a deep understanding of Java internals, but it is my understanding that, when a compiler needs to instantiate a derived class, it has to first create the base (and its base before that(...)) and then slap on the extensions made in the subclass.
So it is not even the danger of uninited variables or anything like that at all. When you try to do something in the subclass' constructor before the base class' constructor, you are basically asking the compiler to extend a base object instance that doesn't exist yet.
Edit:In your case, MyClass becomes the base object, and MyClassMock is a subclass.
I don't know how Java is implemented internally, but if the constructor of the superclass throws an exception, then there isn't a instance of the class you extend. It would be impossible to call the toString() or equals() methods, for example, since they are inherited in most cases.
Java may allow a try/catch around the super() call in the constructor if 1. you override ALL methods from the superclasses, and 2. you don't use the super.XXX() clause, but that all sounds too complicated to me.
I know this question has numerous answers, but I'd like to give my little tidbit on why this wouldn't be allowed, specifically to answer why Java does not allow you to do this. So here you go...
Now, keep in mind that super() has to be called before anything else in a subclass's constructor, so, if you did use try and catch blocks around your super() call, the blocks would have to look like this:
try {
super();
...
} catch (Exception e) {
super(); //This line will throw the same error...
...
}
If super() fails in the try block, it HAS to be executed first in the catch block, so that super runs before anything in your subclass`s constructor. This leaves you with the same problem you had at the beginning: if an exception is thrown, it isn't caught. (In this case it just gets thrown again in the catch block.)
Now, the above code is in no way allowed by Java either. This code may execute half of the first super call, and then call it again, which could cause some problems with some super classes.
Now, the reason that Java doesn't let you throw an exception instead of calling super() is because the exception could be caught somewhere else, and the program would continue without calling super() on your subclass object, and possibly because the exception could take your object as a parameter and try to change the value of inherited instance variables, which would not yet have been initialized.
One way to get around it is by calling a private static function. The try-catch can then be placed in the function body.
public class Test {
public Test() {
this(Test.getObjectThatMightThrowException());
}
public Test(Object o) {
//...
}
private static final Object getObjectThatMightThrowException() {
try {
return new ObjectThatMightThrowAnException();
} catch(RuntimeException rtx) {
throw new RuntimeException("It threw an exception!!!", rtx);
}
}
}