简体   繁体   中英

Creating an array inside a static method accessible from main Java

This is my poor attempt at trying to create an array inside a static method. What this program does is list documents that have a certain extension. I want to be able to store them in an array and access that array from main. Is it possible? This is my code so far:

package recogniseKeywords;

import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;

import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

public class KeywordsRecognition {

    public static void listFilesForFolder(final File folder) {

        String[] files = {};
        int fileSize = 0;

        String[] extensions = {".doc", ".docm", ".xls"};

        for (final File fileEntry : folder.listFiles()) {
            if (fileEntry.isDirectory()) {
                listFilesForFolder(fileEntry);
            } else {

                for(int i=0; i<extensions.length; i++) {
                    //Check if contains one of the extensions and isn't a temporary file(~$)
                    if (fileEntry.getName().contains(extensions[i]) && !fileEntry.getName().startsWith("~$")) {
                        System.out.println(fileEntry.getName());
                        files[fileSize] = fileEntry.getName();
                        fileSize++;
                    }
                }
            }
        }

    }

    public static void main(String[] args) throws Exception {

        String[] keywords = {"Performance Enhancement", "Functional Specification", "Technical Specification", "Faults", "Arval", "Vehicle", "Fines", "Insurance"};


            final File folder = new File("C:/work");
            listFilesForFolder(folder);

            System.out.println(Arrays.toString(files));

        }
    }
}

I am aware that this is a static method and that int, as well as the array, is not treated as in a non-static method, however, I don't know how to proceed further.

The best pointer I can give you is to leave the clutches of the static realm and go into instance-land, the land of object-oriented opportunities!

In your main method do this:

public static void main(String[] args) throws Exception {    
    KeywordsRecognition app = new KeywordsRecognition();
    app.start();
}

Then implement the start method and start your work there. Doing this will give you more options in your code design, allowing you to write more readable and testable code, and thus code with less bugs and maintenance issues.

To access the result of listFilesForFolder you can either return it, assign it to a field, or add it to a collection. Since you are recursing I would say: add it to a collection.

Rationale: each recursion adds to the same collection. You don't want intermediate results visible to other code than the recursion so avoid a field and use a method parameter. Also, it's quite common to pass data through a recursion in this manner, so other developers will understand it.

private static final String ROOT_FOLDER_DEFAULT = "C:/work";
private static final String[] EXTENSIONS = {".doc", ".docm", ".xls"};
// TODO: the keywords are not used anywhere yet
private static final String[] KEYWORDS = {"Performance Enhancement", "Functional Specification", "Technical Specification", "Faults", "Arval", "Vehicle", "Fines", "Insurance"};

public void start(String rootFolder) {       
    List<String> files = new ArrayList<>();
    readFilesRecursively(new File(rootFolder), files);
    // trick to print list contents by converting to array
    System.out.println(Arrays.toString(files.toArray()));
}        

// recursion is not that common so when you use it, 
// it's a good idea to clearly indicate this in the method name
public void readFilesRecursively(File folder, List<String> files) {
    for (File file : folder.listFiles()) {
        if (file.isDirectory()) {
            readFilesRecursively(file, files);
        } else {
            for(String extension : EXTENSIONS) {
                String fileName = file.getName();
                if (fileName.contains(extension ) && !isTemporaryFile(fileName)) {
                    files.add(fileName);
                }
            }
        }
    }
}

// if you find yourself adding a comment in the middle of your code
// that usually means you need to extract a method for that bit
private boolean isTemporaryFile(String fileName) {
    return fileName.startsWith("~$");
}

public static void main(String[] args) throws Exception {    
    KeywordsRecognition app = new KeywordsRecognition();
    app.start(getRootFolder(args));
}

private static String getRootFolder(String[] args) {
    if(args != null && args.length > 0) {
        return args[0];
    }
     else {
        return ROOT_FOLDER_DEFAULT:
    }
}

Sidenote: you cannot increase the size of an array; once you create it, its size is fixed. So either initialize the array to the correct length, or use a java.util.List instead (optionally converting the List to an array after it has been fully populated):

List<String> values = new ArrayList<>();
values.add("1");
values.add("foo");
values.add("elderberries");
String[] valuesAsArray = values.toArray();

Either that, or:

String[] valuesAsArray = new String[3];
values[0] = "1";
values[1] = "foo";
values[2] = "elderberries";

The reason that main can't see the files variable in listFilesForFolder is that files is a local variable . Its scope is the listFilesForFolder method itself. (This would still be true if you declared main and listFilesForFolder as instance methods.)

There are a number of possible solutions. The most straightforward are:

  1. Return the value files as the result of listFilesForFolder , and use the returned value in main .

  2. Declare files as a static variable rather than a local variable.

  3. Declare files as an instance variable, and then change the code to be more object oriented; see Adrian's answer for an example.

Of these approaches, 1 and 3 are better. Approach 2 will work in a simple example like this, but is problematic (for various reasons) in a large application.

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