0

I have a .java file in a folder. I want to get all the methods and every method as a separate file.

class Foo{
public void add(int a, int b){ System.out.println(a+b);}
private int sub(int a, int b,int c){ return a-b;}}

In my program, I want to get all the methods add , sub as separate two files. I know this for .class file.we can achieve it using Reflection, but is it possible for .java file?

  • Does this answer your question? [Is it possible to open a .txt/.java file containing a class, and using reflection on it?](https://stackoverflow.com/questions/9868892/is-it-possible-to-open-a-txt-java-file-containing-a-class-and-using-reflectio) – Oliver Aug 10 '20 at 19:37
  • Sure. You'll need to write a simple parser to get the methods, but that's just programming, and not even too difficult. – NomadMaker Aug 10 '20 at 19:49
  • @NomadMaker thanks for helping me. But in which place I add parser? in a file there are different types of methods like public, private and it may be void or there may be return type.pls explain me – Sanzida Sultana Aug 10 '20 at 19:58
  • @Oliver thanks for your feedback. But I want to get all methods as a separate file from a .java file. – – Sanzida Sultana Aug 10 '20 at 19:59
  • @SanzidaSultana what did you mean by `I want to get all methods as a separate file from a .java file`? – reyad Aug 10 '20 at 20:03
  • @reyad thanks for your feedback. In my code, there are two methods named add and sub.I want to create two separate files like **add.java** which contain the method body "add(int a, int b){ System.out.println(a+b);}" and another file **sub.java** which contain "sub(int a, int b,int c){ return a-b;}". – Sanzida Sultana Aug 10 '20 at 20:23
  • @SanzidaSultana, you don't need reflection for that...you need to write some parser that could extract methods from a class in java...and you can write the parser in any language... – reyad Aug 10 '20 at 20:44
  • @SanzidaSultana, you should take a look at [this](https://stackoverflow.com/questions/2206065/java-parse-java-source-code-extract-methods). – reyad Aug 10 '20 at 20:47
  • 2
    Does this answer your question? [Java : parse java source code, extract methods](https://stackoverflow.com/questions/2206065/java-parse-java-source-code-extract-methods) – reyad Aug 10 '20 at 20:49
  • @reyad I have a project going on where I can't use any kind of software and I am also a beginner. can you pls explain to me step by step how I will do that? It will be a great help. Thanks. – Sanzida Sultana Aug 10 '20 at 21:15
  • @SanzidaSultana, I've added an answer, pls look and tell me if it works for you... – reyad Aug 11 '20 at 00:42

1 Answers1

1

@SanzidaSultana, I've provided the code to extract the methods from a class...This uses regex to extract method from class file. But, this implementation has limitation. Anyway, it'll help you solve your problems. I am just providing the code below(with example).

The parser I've provided, it's very easy to use. All you need is the JavaMethodParser class. Just use it to extract method(with it's name!). See below:

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Note: it is very simple parser
 *       as simple as possible
 *       it's assuming Foo.java is correctly written
 *       it can only track a few errors in Foo.java
 *       is not written in proper format
 *       so, keep that in mind
 *
 *
*/

class JavaMethodParser {
    private List<String> methodList;
    private List<String> methodNameList;
    private int cnt;
    
    public JavaMethodParser(String classContents) {
        Pattern classPattern = Pattern.compile("[a-zA-Z]*\\s*class\\s+([_a-zA-Z]+)\\s*\\{(.*)}$", Pattern.DOTALL);
        
        // now match
        Matcher classMatcher = classPattern.matcher(classContents);

        if(classMatcher.find()) {
            String methodContents = classMatcher.group(2);

            // now parse the methods
            Pattern methodPattern = Pattern.compile("[a-zA-Z]*\\s*[a-zA-Z]+\\s+([_a-zA-Z]+)\\s*?\\(.*?\\)\\s*?\\{", Pattern.DOTALL);

            Matcher methodMatcher = methodPattern.matcher(methodContents);

            List<String> methodStartList = new ArrayList<>();

            // creating method list and methodName list
            methodList = new ArrayList<>();
            methodNameList = new ArrayList<>();

            while(methodMatcher.find()) {
                String methodName = methodMatcher.group(1);
                String methodStart = methodMatcher.group();
                methodStartList.add(methodStart);
                methodNameList.add(methodName);
            }

            // reversing, cause it'll be easier to split
            // methods from the end of methodContents
            Collections.reverse(methodStartList);
            Collections.reverse(methodNameList);
            
            String buf = methodContents;
            int i=0;
            for(String methodStart: methodStartList) {
                String[] t = buf.split(Pattern.quote(methodStart));
                String method = methodStart + t[1];
                
                methodList.add(method);
                
                buf = t[0];
                i++;
            }
        } else {
            System.out.println("error: class not found");
            // throw error, cause not even a class
            // or do whatever you think necessary
        }

        // initializing cnt
        cnt = -1;
    }
    public boolean hasMoreMethods() {
        cnt += 1; // cause, cnt is initialized with -1
        return cnt < methodList.size();
    }
    public String getMethodName() {
        return methodNameList.get(cnt);
    }
    public String getMethod() {
        return methodList.get(cnt);
    }
    public int countMethods() {
        return methodList.size();
    }
}

public class SOTest {
    public static void main(String[] args) {
        try {
            Scanner in = new Scanner(new File("Foo.java"));
            String classContents = in.useDelimiter("\\Z").next().trim();

            JavaMethodParser jmp = new JavaMethodParser(classContents);

            while(jmp.hasMoreMethods()) {
                System.out.println("name: " + jmp.getMethodName());
                System.out.println("definition:\n" + jmp.getMethod());
                System.out.println();
            }

            in.close();
        } catch(FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

The input to this program is Foo.java which is written as below:

public class Foo {
    
    private int u, v;
    private String x;
    
    public int add(int a, int b) {
        if(a + b < 0) {
            return 0;
        }
        return a + b;
    }
    
    public int sub(int a, int b) {
        return a - b;
    }
}

And the output is:

name: sub
definition:
public int sub(int a, int b) {
                return a - b;
        }


name: add
definition:
public int add(int a, int b) {
                if(a + b < 0) {
                        return 0;
                }
                return a + b;
        }

I guess, you know how to write something in file using java. So, I will left that part to you...

[P.S.]: If anything is unclear to you, let me know in the comment section...also provide feedback if its working or not for you...

reyad
  • 1,392
  • 2
  • 7
  • 12
  • @SanzidaSultana, sorry for being late...got stuck into some task....read the answer above and tell me if that works for you... – reyad Aug 11 '20 at 00:40
  • @SanzidaSultana, its not probably appropriate to ask in SO, but I'll ask anyway...are you from Bangladesh, India or may be Pakistaan?...Your name has a subcontinental touch... – reyad Aug 11 '20 at 00:41
  • 1
    Sorry for late. Thanks for your answer. I am trying this with the code you provided and I will tell you if it is working for me or not. and I am Bangladeshi. – Sanzida Sultana Aug 11 '20 at 09:46
  • It's showing me **error: class not found** every time though I pass Foo.java file by scanner class. I think it may be possible only for the class file. I 'm confused – Sanzida Sultana Aug 11 '20 at 15:35
  • @SanzidaSultana, Have you created a file `Foo.java` and put it in the same directory as `SOTest.java`? Its perectly working in my pc...what is your java version? Give me your directory structure... – reyad Aug 11 '20 at 18:24
  • java version "1.8.0_111" Java(TM) SE Runtime Environment (build 1.8.0_111-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode) – Sanzida Sultana Aug 11 '20 at 18:54
  • I created a file Foo.java.And when i print the classContents from the main method its print the file contents.the output is: **class Foo{ public void add(int a, int b){ System.out.println(a+b);} private int sub(int a, int b,int c){ return a-b;}} error: class not found Exception in thread "main" java.lang.NullPointerException at Search.JavaMethodParser.hasMoreMethods(JavaMethodParser.java:76) at Search.SOTest.main(SOTest.java:17) C:\Users\Tech Land\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1 BUILD FAILED ** – Sanzida Sultana Aug 11 '20 at 18:58
  • wait a min...i'm updatng the code...my regex requires very tight match....i am loosing it a bit – reyad Aug 11 '20 at 18:59
  • @SanzidaSultana, I've edited the code....now copy paste the code and test...its working for your input too...and give me feedback as soon as possible... – reyad Aug 11 '20 at 19:01
  • Its worked. Thanksss for your effort. – Sanzida Sultana Aug 11 '20 at 19:09
  • @SanzidaSultana, you're welcome..have a good day... – reyad Aug 11 '20 at 19:10