J Fabian Meier
J Fabian Meier

Reputation: 35785

Parsing method calls: Implicit dependencies on other classes

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

Answers (4)

Kong
Kong

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:

http://spoon.gforge.inria.fr/

There are a good few others; ANTLR, Eclipse...

Upvotes: 1

chengpohi
chengpohi

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:

  • // Method B.getC:()LC; --> used class B
  • // Method C.getD:()LD; --> used class C

but I think the best way is use Abstract Syntax Tree as @Kong,

Upvotes: 1

K&#246;nig Lukas
K&#246;nig Lukas

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

BlackJoker
BlackJoker

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

Related Questions