简体   繁体   中英

Getting around type-checking

This is exceedingly bad OO, but I am not trying to put this in any kind of code that will be used by anyone but the coders themselves -- it can never be called except for testing by coders.

Here is the problem I am facing: I have a series of classes that are defined externally. I cannot modify them in any way (except of course I could subclass or call them). They have a variety of names but they do not extend any superclasses (except Object), or implement any interfaces. However what I know about each of them is that they have a method called 'call'.

For testing, I am trying to write code that will call any one of these classes' call methods. But, of course, I cannot just say Object.call() because call is not defined for every Object.

Essentially, this will work:

MyClassOne classOne = new MyClassOne();
MyClassOneInput classOneInput = new MyclassOneInput();

classOne.call(classOneInput);

But this will not:

Object clazz = getClassFromElsewhere();
Object clazzInput = getClassInputFromElsewhere();

clazz.call(clazzInput).

Obviously, since Java is a strongly typed language.

BUT, for the sake of 10x faster testing for every person working on this system, can I get around that somehow and somehow use the 'call' method for any Class and any ClassInput? I have no problem if it generates an exception or breaks entirely if the wrong classes are passed.

Please help me violate Object Orientation.

You can use reflection to do this. Check out the reflection API

Here is a simple example:

MyClassOne classOne = new MyClassOne();
MyClassOneInput classOneInput = new MyClassOneInput();
Method m = classOne.getClass().getMethod("call", MyClassOneInput.class);
m.invoke(classOne, classOneInput);

Note: you can use getDeclaredMethod to get any method, including private and protected ones but you'll need to call "m.setAccessible(true)" on them if they are private/protected.

This is a perfect use for Java Reflection . This is a pseudo-code example, but it would look something like this

 Object obj = getExternalObject();
 Method meth = obj.getClass().getDeclaredMethod("call");
 meth.invoke(obj);

Use Reflection

  1. get the class using getClass()
  2. find the "call" method using getMethod()
  3. invoke it on the object if found

eg

java.lang.reflect.Method method;
try {
  method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) {
  // ...
} catch (NoSuchMethodException e) {
  // ...
}

Then

try {
  method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {

see How do I invoke a Java method when given the method name as a string?

I would also consider looking into Dynamic JVM languages (JRuby, Jython, Groovy) in which doing something like this may look less "Bad OO" and feel more natural

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM