繁体   English   中英

方法退出时,新的ArrayList对象消失

[英]New ArrayList Objects Disappear When Method Exits

您好,并提前致谢。 我在这里相对较新,到目前为止,我已经能够解决我从搜索中遇到的任何问题,但这个问题令我难过。

我正在编写一个程序,使用Rest-Assured进行API调用以获取云服务器中不同对象的配置文件。 这些对象是我们可以调用文件夹的组织文件容器。 文件夹具有特定结构,每个文件夹具有特定的元数据配置文件。 我的程序所做的是从返回的JSON创建java对象,并以允许它们仍然像文件夹结构一样工作的方式存储它们,以便可以操作它们来执行以下操作:打印文件夹结构,获取特定的子文件夹文件夹,视图名称或特定文件夹的ID,添加或删除文件夹等。

我已经设置了这个,所以每个文件夹都是一个对象,它包含子文件夹的ArrayList和元数据的变量,构造函数将根据JSON填充所有变量。

在使用我的递归方法调用API并将子文件夹添加到它们应该去的位置之后,在类中的方法中我可以看到它们被正确添加,一旦方法退出,如果我尝试从Main访问列表我得到一个空指针异常。 请参阅下面的代码示例

编辑:我已经在下面的代码中添加了额外的测试,以检查递归方法中的数组索引是否为空。 创建对象时,构造函数使用indexOf()在ArrayList中打印文件夹ID和索引。 当它从构造函数返回时,在同一个递归方法中, getSingleFolder(index).getSubfolders().get(0).getSubfolders().get(0).toString仍然为null,即使这应该返回相同的文件夹刚刚创建并从构造函数中添加到父文件夹ArrayList(并验证)。

        public void saveSubfoldersRecursively(Folder folder){
        if (folder.hasSubfolders()){
            getFolderSubfoldersJsonArrayFromRestApi(folder);

            for(int x = 0; x < folder.getFoldersJsonArray().size(); x++) {
                JsonObject currentSubfolderJson = folder.getFoldersJsonArray().get(x).getAsJsonObject();
                JsonObject fullSubfolderProfileObject = getFolderProfileFromRestApi(currentSubfolderJson);
                Folder newSubfolder = folder.addSubfolder(fullSubfolderProfileObject);

                if (newSubfolder.hasSubfolders()) {
                    saveSubfoldersRecursively(newSubfolder);
                }
            }
            if (folder.getId().equals("<folderID>") ) {
                System.out.println("inside saveSubfoldersRecursively");  // this prints fine
// Null Pointer Exception at next line!
                System.out.println("access test 1: " + folder.getId() + " subfolder at index 0: " + folder.getSubFolders().get(0)); 
        }
    }

根据要求, getFolderProfileFromRestApi()getFoldersJsonArrayFromRestApi()方法只是使用Rest-Assured进行调用,并返回一个GSON JsonObject,其中包含其函数所需的构造函数或方法所需的信息,我已经使用了这些,已经证实他们按预期工作。 调用folder.addSubfolder()调用文件夹构造函数并返回新文件夹,以便它可以用来获取它自己的文件夹等。我已经广泛使用它并验证它确实返回了正确的信息和构造函数叫做。 如果我将System.out检查放在实际的folder.addSubfolder()方法中,我可以访问数组中的元素,因为它们仍在那里但当控制返回到main时似乎消失了。

Folder类中的addSubfolder方法如下所示。 我添加了系统输出以检查并确保一切都在发生,并且这些实际上已添加到他们应该的位置。 这里的输出完全符合预期。

public Folder addSubfolder(JsonObject folderProfile){
    System.out.println("Adding " + folderProfile.get("id") + " to subfolders of " + this.getId());        //this is a check to be sure the folderProfile passed has the right folderID and has been passed ot the right parent folder. this also returns the correct info in all cases
    Folder subfolder = new Folder(folderProfile);
    this.subFolders.add(subfolder);
    System.out.println("subfolder added at index " + this.subFolders.indexOf(subfolder));    //This is just a check to see that the subfolder is now in the array and it does return the correct index. 
    return subfolder;
}

当我返回Main时,我编写了一个小的递归方法,只使用名称以标准格式打印结构,它似乎一直工作,直到它到达第3级的地方,然后它抛出null尝试访问该级别的第一个元素时的指针异常。

相反,我使用特定代码只调用toString用于刚刚在addSubfolder方法中创建和检查的完全嵌套子文件夹,并且它还返回空指针异常。

server.getSinglefolder(1).getSubFolders().get(0).getSubFolders().get(0).toString();

我可以告诉,这个其他StackOverflow帖子

对象消失了ArrayList

有同样的问题,但我似乎无法理解如何为我的情况转换解决方案或如果它不工作,因为我不应该这样做。 谢谢你的帮助!

编辑:我已经再次审阅了该帖子,看来他的问题是一个问题,因为他后来的代码正在改变它,但他没有注意到因为它是一个参考。 我不认为这是这种情况,因为在该方法返回之后,直到在main中调用该对象并且返回空时才再次访问该对象。 我现在一直在寻找和阅读文章,这一定是我看不到的愚蠢。 再次感谢你的帮助。

编辑2:经过进一步测试后,我注意到添加到ArrayList的文件夹在构造函数中是可验证的,使用this来获取对象并为其ID调用getter。 但是,当从调用构造函数的递归方法的末尾访问时,ArrayList在该索引处为null(System.out测试添加到代码示例中)。 因此,一旦构造函数返回,实际上,在控制甚至返回到main之前,arraylist再次为Null。 这可能与我在方法中声明我的占位符对象(文件夹,子文件夹,newSubfolder)这一事实有关,因此它们会在退出时被清除吗? 即使是这种情况,即使临时引用消失,对象本身仍应保持更改。

编辑3:根据要求,这里是folder.hasSubFolders()和文件夹构造函数的方法。

private boolean hasSubfolders;


    public boolean hasSubfolders() {
    return hasSubfolders;
}

从addSubfolder中调用的Folder Constructor。 请注意整个构造函数大约是150行,但它遵循相同的格式,检查JSON中的成员,如果存在,则将值保存到类变量。 如果有人真的认为有必要,我可以发布整件事。

 //main constructor, parses response string to JSON and pulls all data to fill class variables.
public Folder(JsonObject folderProfile) {

    if (folderProfile.has("database")) {
        this.database = folderProfile.get("database").getAsString();
    }

    if (folderProfile.has("default_security")) {
        this.defaultSecurity = folderProfile.get("default_security").getAsString();
        }
...}

编辑5:程序的每个部分的ideone链接。 它当然不会在没有访问其余服务器的情况下运行,但遗憾的是我无法共享连接信息。 我可以向你保证,其余的调用功能正常,并准确返回他们应该的数据,并且所有数据都被正确处理(正确,因为有效的方式,但可能不是最佳实践)-_-

注意:我知道我需要清理抽象类及其实现方式,我还有很多工作要做,以清理编码实践,但这远远不完整,只有半成品我正在测试的程序。 但是我对这个领域的任何建议完全开放,因为我一直在学习。 谢谢

主要 - https://ideone.com/Y2FYrm

IMContainer - https://ideone.com/TFdiqk

文件夹 - https://ideone.com/gX4nda

模板 - https://ideone.com/7VfkPX

服务器 - https://ideone.com/geJazD

我怀疑当您以递归方式将文件夹添加到文件夹arrayList时,您不会将子文件夹添加到添加的子文件夹中。 这会创建一个场景,其中第三个递归的子文件夹抛出NullPointerException。 如果这是唯一的问题,移动

if (newSubfolder.hasSubfolders()) {
    saveSubfoldersRecursively(newSubfolder);
}

到方法的开头可能有所帮助。

但是,不知道实施

getFolderSubfoldersJsonArrayFromRestApi

要么

getFolderProfileFromRestApi

我不能肯定地说。

我同意Chi-Young Jeffrey Lii的回答,这是对此的进一步阐述。 addSubfolder()基本上做了3件事。

public Folder addSubfolder(JsonObject folderProfile){
     System.out.println("Adding " + folderProfile.get("id") + " to subfolders of " + this.getId());
     // 1.create new subfolder
     Folder subfolder = new Folder(folderProfile);
     // 2.add subfolder to this subFolders arraylist
     this.subFolders.add(subfolder);
     System.out.println("subfolder added at index " + this.subFolders.indexOf(subfolder));    
     // 3.return subfolder
     return subfolder;

}

如下图所示 在此输入图像描述

当语句执行时(与图表颜色匹配高亮颜色),蓝色部分是一个空的ArrayList ,如果你调用.get(0) ,它将返回一个null。 如果在null变量上调用toString() ,它将抛出空指针异常。 在此输入图像描述 在此输入图像描述

由于我们无法访问所有代码,因此这是我们可以猜测根本原因的最佳假设。


编辑1

我认为你很困惑为什么在addSubfolder()获取索引但是当你在saveSubfoldersRecursively()检查它时,它会给你错误。 这是因为两个陈述指向不同的参考。

System.out.println("access test 1: " + folder.getId() + " subfolder at index 0: " + folder.getSubFolders().get(0)); 

不等于

System.out.println("subfolder added at index " + this.subFolders.indexOf(subfolder));    

我打赌如果你在addSubfolder()的最后一行写这个也会给你带来异常。

System.out.println("subfolder's subfolder null check:" + subfolder.getSubFolders().get(0).toString());

编辑2

给出的源代码说明。 我发现Folder有自己的子文件夹,模板也有自己的子文件夹。 它们是不同的文件夹列表,如何向Template类添加子文件夹可以从模板中检索回来?

在此输入图像描述

暂无
暂无

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

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