I know Java can get Method Object using the Reflection.getMethod(...) method,but the method needs method parameter types。 but I don't know the exact parameter type。e.g.
byte a = 20;
System.out.println(a);
the println method hasn't the overload method println(Byte),but has println(Int)。
How to get the println method through the byte type?
the other example
class MyClass
{
}
class MyClass1 extends MyClass
{
}
class TestClass
{
public static void method1(MyClass c)
{
... ...
}
}
TestClass.method1(new MyClass1()) is correct.but can i get the method1 through parameter type MyClass1 ?
Class.getMethods will get all method in Class, too much。 can i get all overload method same name?
java.lang.Class (see JavaDoc) provides two ways of finding methods:
Method getMethod(String name, Class<?>... parameterTypes)
and
Method[] getMethods()
(and corresponding getDeclaredMethod() variants).
So there's no API in the standard Java library for directly getting what you need - you'll need to get all methods, filter the ones with the right name, then inspect the parameter types.
Or you may be able to find a 3rd-party library that will do this for you. For example, the reflections library has a getMethodsMatchParams(Class<?>... types) method.
The jOOR library also provides various methods for finding methods with "similar" signatures.
Related
Is something like that possible.
List<?> myList = getMyList();
class cls = class.forname("com.lab.myClass");
cls = myList.get(0);
cls.getValue();
Create an Instance with the fully-qualified name of a class and use their declared Methods?
No, if you call Class.forName, at compile time you know nothing about the returned Class instance. You don't even know that it represents a class; it might be an interface for example. In particular, if it is a class and you create an instance of it, you cannot call any methods of it except those which are already defined in Object because, at compile time, the compiler cannot check whether these methods exist.
The are two solutions:
First, you can use reflection to find out about the methods the class has, and to call these methods. This is very cumbersome.
Second, if you use Class.forName to dynamically load classes at runtime, often you know something about the classes you load. For example, you might know that the class implements a certain interface. Then you can cast the result of newInstance to this interface and then call the methods defined in this interface directly.
For example:
// in file Plugin.java
interface Plugin {
void doSomething();
}
// in file Main.java
public class Main {
...
void runPlugin() {
try {
Class<?> pluginClass = Class.forName("pkg.name.MyPlugin");
Plugin plugin = (Plugin) pluginClass.newInstance();
plugin.doSomething();
}
catch (...) {
// catch the necessary exceptions
}
}
}
I have class named: ComplexValidator that extends absract class Validator which have two methods:
Validate(Part part);
getAnswer():
I also have validators, lets name them A, B, C and D.
So
AValidator extends Validator
BValidator extends Validator
CValidator extends Validator
DValidator extends Validator
I am not in front of my code right not so I will use pseudo-code.
CValidator takes different parameter than rest of it, A B and D uses part to get filename etc, but CValidator uses numberOfFiles (which are increased in loop (for part p: multipart) so after every time loop is repeated numberoffiles is increased so I can compare it with maxNumberOfFiles field).
Sadly I didnt know how to make abstract class that will take any parameter to method so all methods must take Part part. Cvalidator doesnt use it and I had to make field numberOfFiles static so I can get access to it.
Is there any way to make those validators takes no parameters but no using static?
Is there any way to make abstract class the way that child classes will be able to change arguments it take?
And if it takes other arguments HOW can I loop it all when I have:
List <Validator> validators = new ArrayList<>();
in my ComplexValidator.
and then I add all child validators to it and loop over them like that:
for (Validator v: validators){
validate(part);
}
The types of the parameters of an overriden method must be the same as the original method.
To face your problem I would create a custom class that wraps all the different parameters that you might want to pass to the validate function.
Something like that
class Wrapper{
Part param1;
File param2;
File param3;
}
class Validator{
void validate (Wrapper wrapper);
}
class ValidatorA extends Validate{
void validate (Wrapper wrapper){
//use wrapper.part...
}
}
class ValidatorC extends Validate{
void validate (Wrapper wrapper){
//use wrapper.file...
}
}
You may want to use java reflection. With a Class you can either getMethods and loop throught the methods and getParameterTypes of each method or if you know in advance the types of the method you wish you can getMethod (without s) and provide an array of type.
In your case I would go to the first method and depending on the presence of the second parameter (number of files), invoke the method the good way (with all the parameters needed).
My question is as follows; please assist.
I have an annotation applicable to methods only that i want to be processed at runtime, say
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnno {
String name();}
And here is my processor:
public class MyAnnoProcessor(Class cls){
Method[] m = cls.getClass().getMethods();
...// read the value passed to name and create an instance of an object depending on the value of 'name'
Yes. MyAnnoProcessor code is as follows:
public class MyAnnoProcessor(Class cls){
Method[] methods = cls.getMethods();
for(Method m: methods){
MyAnno an = (MyAnno) m.getAnnotation(MyAnno.class);
if(an!=null)
sysout(an.name());
....//call another method to create a class based on the value passed to 'name'
Now, i have a class where i want to write many methods annotated with #MyAnno but each method passes a different value to "name". Am just unable to figure out a way to handle the annotation processing in an ideal way? How should 'MyAnnoProcessor' know what (object) needs to be returned to which method?
Say, i do this in a method A:
#MyAnno(name="testA")
public void A(){
MyAnnoProcessor(this);
...}
And again i do this in method B:
#MyAnno(name="testB")
public void B(){
MyAnnoProcessor(this);
...}
The 'MyAnnoProcessor' seems to read the value of 'name' as "testA" and not "testB" in the subsequent call to it from method B. Where am i mistaken? Please advise.
If you want to find annotations for a single method, you could first get the method using reflection and the do a getDeclaredAnnotations(). Something like
Class clazz = ...//obtain class object
Method method = clazz.getMethod("A", null);
Alternatively, with your current code, you can still loop through all methods and do a matching for the method name by doing m.getName() inside your for loop to find out which method you're looking at right now.
P.S: I'm not entirely sure your code would compile (MyAnnoProcessor, i don't see any methods) and please try to follow naming conventions for methods)
I am trying to use javassist to programatically create and compile a class (at runtime) that implements an interface.
I get the following Error whenever I invoke an instance of that dynamic class:
java.lang.AbstractMethodError: FooImpl.test()Ljava/lang/Object;
Here's my interface
public class FooBarInterface<T> {
public T getEntity();
}
Here's a sample Entity
public class FooEntity {
#Override
public String toString() {
return "Hello, Foo!";
}
}
Here's how I programatically implement the interface
public void test() {
ClassPool classPool = ClassPool.getDefault();
CtClass testInterface = classPool.get(FooBarInterface.class.getName());
CtClass fooImpl = classPool.makeClass("FooImpl");
fooImpl.addInterface(testInterface);
CtMethod testMethod = CtNewMethod.make(
"public com.test.FooEntity getEntity(){" +
"return new com.test.FooEntity();" +
"}",
canImpl
);
fooImpl.addMethod(testMethod);
fooImpl.writeFile();
TestInterface<FooEntity> test =
(TestInterface<FooEntity>) fooImpl.toClass().newInstance();
System.out.println(test.getEntity());
}
If I changed the return type of the implemented method to Object, then I don't get the Error, like this:
CtMethod testMethod = CtNewMethod.make(
"public Object getEntity(){" +
"return new com.test.FooEntity();" +
"}",
canImpl
);
Then I successfully get the hello, Foo!. I am OK with changing the return type to Object, but I'd like to understand more why returning with type Foo produces AbstractMethodError.
Inside the JVM, methods with different return types are distinct. After type erasure, FooBarEntity.getEntity() has return type Object. Calls via the interface will look specifically for a method with return type Object, hence why your implementation must return Object.
Normally, your Java compiler will create bridge methods that forward the result of the concrete method as the erased type, but apparently Javassist doesn't do this for you (I haven't used Javassist so I'm not sure).
For more on how bridge methods are used to implement type erasure, see the official Java Tutorials topic on bridge methods.
I was having same error. I had a base class in which I declared a new abstract method. I implemented that method on the other classes that were consuming it. Now on debugging I was getting Abstract method error as soon as I was hitting implementation of the method.
Solution-:
I figured that base class been consumed by other artifacts too and I didn't overrode newly created abstract method in those artifacts. Since I never build them as I was not changing them, JVM never throws compile time error but on run time exception occurs.
On implementing method in other artifacts I was able to get rid of the exception.Basically in my case all child classes didn't have implementation of base class's abstract method.
When you have a parameterized parameter or return type, the Java compiler compiles it as though it was Object and synthesizes a bridge method with the parameterized signature that calls the other one. Or possibly the other way around. You've only synthesized one of them, not both.
Suppose you have a generic interface and an implementation:
public interface MyInterface<T> {
void foo(T param);
}
public class MyImplementation<T> implements MyInterface<T> {
void foo(T param) {
}
}
These two types are framework types I provide. In the next step I want allow users to extend that interface as well as redeclare foo(T param) to maybe equip it with further annotations.
public interface MyExtendedInterface extends MyInterface<Bar> {
#Override
void foo(Bar param);
// Further declared methods
}
I create an AOP proxy for the extended interface and intercept especially the calls to furtherly declared methods. As foo(…) is now redeclared in MyExtendedInterface I cannot execute it by simply invoking MethodInvocation.proceed() as the instance of MyImplementation only implements MyInterface.foo(…) and not MyExtendedInterface.foo(…).
So is there a way to get access to the method that declared a method initially? Regarding this example is there a way to find out that foo(Bar param) was declared in MyInterface originally and get access to the accoriding Method instance?
I already tried to scan base class methods to match by name and parameter types but that doesn't work out as generics pop in and MyImplementation.getMethod("foo", Bar.class) obviously throws a NoSuchMethodException. I already know that MyExtendedInterface types MyInterface to Bar. So If I could create some kind of "typed view" on MyImplementation my math algorithm could work out actually.
Additional info:
I create the proxy for the MyExtendedInterface as follows:
ProxyFactory factory = new ProxyFactory();
factory.setTarget(new MyImplementation());
factory.setInterfaces(new Class[] { MyExtendedInterface.class });
factory.addInterceptor(new MyInterceptor(MyExtendedInterface.class));
The interceptor pretty much scans the methods and executes JPA queries for all methods declared in MyExtendedInterface but routes all method invocations of methods declared in MyInterface to the proxy target. This works as long as methods from MyInterface are not redeclared as the target then doesn't implement it anymore.
public class MyInterceptor implements MethodInterceptor {
public Object invoke(final MethodInvocation invocation)
throws Throwable {
// handling of query methods
// else
invocation.proceed();
// ^^ works if not redeclared but not if
}
}
So what I would like to do instead of invocation.proceed() is detect the method that originally declared the one being invoked and invoke that on the target manually.
Okay, here's the solution I came up with: As I know the base class and it generics structure (what T means in this case) as well as MyExtendedInterface types MyInterface to Bar I can scan the base implementation for possible matches as follows (pseudocode):
for all methods {
skip those with non matching name and parameters length;
for all generic parametertypes {
if typename = T then concrete type has to be Bar
...
}
}
I don't need a generic solution in this case so that seems to work.
The whole scenario seems strange. You can't apply AOP declared on MyExtendedInterface to MyImplementation, because it does not implement it.
Second, I don't understand why it matters which interface defines a method, since it is the implementation that the method is invoked on.
Apart from that, you can get all the methods declared by a certain class/interface by getDeclaredMethods(). Then you can iterate on them and find something that matches your criteria (name)