Reputation: 35785
I am trying to parse all method calls in a java source code file and relate them to their respective classes. First of all, I thought I only need to look for classes that are imported through import statements (our company guidelines forbid *-imports). Then I could find out where variables of this type are used and record their method calls.
Then I noticed that there are constructions like
A.getB().getC()
The class B is actually never imported (because it is not explicitly used), but its function getC() is called (and the source code somehow implicitly "depends" on it).
Are there other such cases?
Upvotes: 2
Views: 365
Reputation: 9546
Not the exact answer you are looking for, but you are probably better off building up an Abstract Syntax Tree (or similar) of the class through an existing library, rather than trying to parse the source code yourself.
Then you will be able to see exactly what you have.
Here's an example:
There are a good few others; ANTLR, Eclipse...
Upvotes: 1
Reputation: 14217
You maybe intrested in javap
I have created A.java, B.java, C.java, D.java fiels:
public class A {
public static void main(String[] args) {
B b = new B();
b.getC().getD();
}
}
and compile these classes.
Now we can use javap to dissemble A.class:
javap -c A
and get bytecodes:
public class A { public A(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":() 4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class B
3: dup
4: invokespecial #3 // Method B."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method B.getC:()LC;
12: invokevirtual #5 // Method C.getD:()LD;
15: pop
16: return
}
Now you can get A.class have used imported class, like:
but I think the best way is use Abstract Syntax Tree as @Kong,
Upvotes: 1
Reputation: 41
Obviously, classes from the same package do not appear in the import statements. (You probably already realized that, but just in case.)
Also, using reflections, there are probably many ways to use classes that are not imported (see the answer just posted by Black Joker).
Furthermore, you can fully qualify classes directly in a statement by
package.subpackage.Class
They aren't imported either.
Upvotes: 2
Reputation: 3191
Yes.you can use Class.forName(xxx)
to load the Class B in runtime. like this :
//get Class object of B
Class classB = Class.forName("package.to.B");
//get Method object of C in class
Method methodC = classB.getMethod("C", parameterTypes of methodC);
//for static method:
methodC.invoke(null, args of methodC);
//create an instance of class B:
Object instanceOfB = classB.newInstance();
// invoke the method C on this instance
methodC.invoke(instanceOfB, args of methodC);
Upvotes: 1