简体   繁体   English

在可从主Java访问的静态方法中创建数组

[英]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. 我希望能够将它们存储在数组中并从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. 我知道这是一个静态方法,并且不将int以及数组视为非静态方法,但是,我不知道如何进一步进行。

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. 然后实施start方法并在那里开始工作。 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. 要访问listFilesForFolder的结果,可以将其返回,将其分配给字段或将其添加到集合中。 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): 因此,要么将数组初始化为正确的长度,要么使用java.util.List代替(可以选择在完全填充List之后将其转换为数组):

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 . mainlistFilesForFolder中看不到files变量的原因是files是一个局部变量 Its scope is the listFilesForFolder method itself. 它的范围是listFilesForFolder方法本身。 (This would still be true if you declared main and listFilesForFolder as instance methods.) (如果您将mainlistFilesForFolder声明为实例方法,则情况仍然如此。)

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 . 返回值files作为listFilesForFolder的结果,并在main使用返回的值。

  2. Declare files as a static variable rather than a local variable. files声明为static变量,而不是局部变量。

  3. Declare files as an instance variable, and then change the code to be more object oriented; files声明为实例变量,然后将代码更改为更面向对象。 see Adrian's answer for an example. 参见Adrian的答案。

Of these approaches, 1 and 3 are better. 在这些方法中,1和3更好。 Approach 2 will work in a simple example like this, but is problematic (for various reasons) in a large application. 方法2将在类似这样的简单示例中工作,但是(由于各种原因)在大型应用程序中会出现问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM