您好,谢谢。我在这里相对较新,到目前为止,我已经能够解决搜索过程中遇到的任何问题,但是这个问题让我很困惑。
我正在编写一个程序,该程序使用Rest-Assured进行API调用以获取云服务器中不同对象的配置文件。这些对象是我们可以称为文件夹的组织文件容器。文件夹具有特定的结构,每个文件夹都有特定的元数据配置文件。我的程序要做的是根据返回的JSON创建Java对象,并以允许它们像文件夹结构一样工作的方式存储它们,以便可以对它们进行操作,例如:打印文件夹结构,获取特定文件夹的子文件夹文件夹,查看特定文件夹的名称或ID,添加或删除文件夹等。
我已经进行了设置,以便每个文件夹都是一个对象,其中包含其子文件夹和元数据变量的ArrayList,构造函数将根据JSON填充所有变量。
使用递归方法调用API并将子文件夹添加到它们应该去的位置后,在类内的方法内,如果我尝试访问该方法,则一旦方法退出,我可以看到它们已正确添加。从主列表我得到一个空指针异常。请参见下面的代码示例。
编辑:我在下面的代码中添加了附加测试,以检查递归方法中的数组索引是否为null。创建对象时,构造函数使用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调用了刚创建的嵌套子文件夹的toString,并在addSubfolder方法中对其进行了检查,它还返回了空指针异常。即
server.getSinglefolder(1).getSubFolders().get(0).getSubFolders().get(0).toString();
据我所知,这是另外一个StackOverflow帖子
Objects disappearing of 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构造函数。请注意,整个构造函数大约有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链接。它无法在没有访问其余服务器的情况下运行,但是很遗憾,我无法共享连接信息。我可以向您保证,其余的调用可以正常运行,并准确返回应有的数据,并且所有这些数据都得到了正确处理(以一种有效的方式正确处理,但可能不是最佳实践)-_-
注意:我知道我需要清理抽象类及其实现方式,我还有很多工作要做以清理编码实践,但这还远远没有完成,只有一半-完成了我正在测试的程序。但是,由于我一直在学习,因此我完全欢迎该领域的任何建议。谢谢
IMContainer-https://ideone.com/TFdiqk
答案 0 :(得分:2)
我怀疑当您将文件夹递归添加到文件夹arrayList时,您没有将子文件夹添加到添加的子文件夹中。这将创建一个方案,其中子文件夹第三次递归抛出NullPointerException。如果这是唯一的问题,请移动
if (newSubfolder.hasSubfolders()) {
saveSubfoldersRecursively(newSubfolder);
}
方法开头可能会有帮助。
但是,不知道
的实现getFolderSubfoldersJsonArrayFromRestApi
或
getFolderProfileFromRestApi
我不能肯定地说。
答案 1 :(得分:1)
我同意Chi-Young Jeffrey Lii的回答,这是对此的进一步阐述。
addSubfolder()
基本上做了三件事。
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)
,它将返回空值。如果对空变量调用toString()
,它将引发空指针异常。
由于我们无法访问所有代码,因此这是我们可以猜测根本原因的最佳假设。
我认为您很困惑为什么在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());
对给定源代码的解释。我发现Folder有自己的subFolders,而Template也有它自己的。它们是不同的文件夹列表,如何从模板中检索如何向文件夹类添加子文件夹?