可能与类对象ArrayList数据存储相关的未知StackOverflow错误(&A
以下是我收到的错误代码:
Exception in thread "main" java.lang.StackOverflowError
at JavaKeywords.<init>(JavaKeywords.java:5)
at LAddClass.<init>(LAddClass.java:8)
at LStore.<init>(LStore.java:9)
at LAddClass.<init>(LAddClass.java:9)
at LStore.<init>(LStore.java:9)
下面是上面提到的三个类。很抱歉发布了几乎整个程序的代码,但我真的不知道错误在哪里。下面突出显示了错误代码生成的三行代码。
这是一个UMLtoJava转换器的程序。用户必须输入类名和类类型(公共/私有),并将变量存储在虚拟类中。我已经创建了一个类Object的ArrayList来存储用户的输入,即字符串className和布尔值isPrivate。稍后,必须在图形用户界面窗口中打印类名和类型,以便用户复制文本。
我猜错误与无法将值(String className, String classMethod, boolean isPrivate
)存储到ArrayList<LStore>
有关,ArrayList<LStore>
是LStore类的对象的arrayList。我以前遇到过一个空指针异常错误,它应该与数组列表有关,在我更改了一些代码和类名之后,我得到了这个新的stackOverFlow
错误。
LAddClass class
用于使用checkName()
并将bolean isPrivate
转换为字符串以供以后使用
public class LAddClass{
private String className;
private String methodName;
private boolean isPrivate;
JavaKeywords keyObject = new JavaKeywords();
LStore stObject = new LStore(className, methodName,isPrivate);//<<<<<<<<<<<<<<<<<<<<<<<<<<< related to the error
public String getPublic(){
String s;
if (stObject.getIsPrivate() == true)
s = " private";
else
s = "public";
return s;
}
public void setPublic(){
}
public boolean checkName(String name){
boolean check = true;
for (int i=0; i<=stObject.getListSize(); i++){
if (keyObject.containsKeyword(name) || name.equals(stObject.getClassName())){
boolean o = false;
check = o;
}// end if
}// end for
return check;
}// end checkName
}//end class
LStore class
是用于将变量存储到ArrayList<LStore>
import java.util.*;
public class LStore {
public static ArrayList<LStore> classes = new ArrayList<LStore>();
public boolean isPrivate;
public String className;
public String methodName;
LAddClass classObject = new LAddClass(); //<<<<<<<<<<<<<<<<<<<<<<<<<<< related to the error
public LStore(String name, String method, boolean isP){
this.className = name;
this.isPrivate = isP;
this.methodName = method;
classes.add(this);
}
public String getClassName(){
return className;
}
public String getMethodName(){
return methodName;
}
public boolean getIsPrivate(){
return isPrivate;
}
public int getListSize(){
return classes.size();
}
public String getJavaCode(){
String javaCode = (classObject.getPublic() + " " + className +"{
"+" "+methodName+"
}"+"}");
return javaCode;
}
}
和这里的图形用户界面类GuiAddClass
供用户创建新类。我认为它也可能包含一些错误,所以我会把这个放在上面以供参考。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GuiAddClass extends JFrame{
LAddClass classObject = new LAddClass();
private JRadioButton publicButton, privateButton;
private JLabel clazz;
private JTextField inputClassName;
private JLabel mothod;
private JTextField inputMethodName;
private JLabel note;
private JButton confirmButton;
private JButton cancelButton;
public GuiAddClass(){
super("Create class");
setLayout(new FlowLayout());
publicButton = new JRadioButton("public", false);
privateButton = new JRadioButton("private", true);
clazz = new JLabel("Class Name: ");
inputClassName = new JTextField("ExampleClass",10);
mothod = new JLabel("Method Name*: ");
inputMethodName = new JTextField("doSomething()",10);
note = new JLabel("*All methods are public void in default. You may only create one method for a class.");
confirmButton = new JButton("Confirm");
cancelButton = new JButton("Cancel");
add(publicButton);
add(privateButton);
add(clazz);
add(inputClassName);
add(mothod);
add(inputMethodName);
add(note);
add(confirmButton);
add(cancelButton);
ButtonGroup group = new ButtonGroup();
group.add(publicButton);
group.add(privateButton);
Handler handler = new Handler();
NewHandler newhandler = new NewHandler();
confirmButton.addActionListener(handler);
cancelButton.addActionListener(newhandler);
}// end constructor AddClass()
private class Handler implements ActionListener{
public void actionPerformed(ActionEvent event){
String cName = inputClassName.getText();
String mName = inputMethodName.getText();
boolean isP = true;
if (classObject.checkName(cName) == false){
JOptionPane.showMessageDialog(null, "Class name invalid. " +
"
Entered name should not contain java keywords or equal to other existing names. " +
"
Please try again.");
} else if (classObject.checkName(cName) == true) {
JOptionPane.showMessageDialog(null, "Class saved.");
cName = inputClassName.getText();
mName = inputMethodName.getText();
if (event.getSource() == publicButton) {
isP = false;
} else if (event.getSource() == privateButton) {
isP = true;
}
new LStore(cName, mName, isP);
}
}// end actionPerformed()
}// end Handler class
private class NewHandler implements ActionListener{
public void actionPerformed(ActionEvent event){
setVisible(false);
}
}
}// end AddClass
JavaKeywords class
最初来自How to check if the class name is valid?,这个类的方法是检查className是否等于Java保留关键字。这也可能与错误有关,因为此类似乎相当频繁地被检测为错误
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
/**
* JavaKeywords is a Utility class related to the reserved keywords
*
* @author MrLore from https://stackoverflow.com/questions/13979172/how-to-check-if-the-class-name-is-valid
*/
public class JavaKeywords
{
private static final HashSet<String> keywords = new HashSet(Arrays.asList(new String[]{
//There are 50 keywords, and 3 literals; true, false and null.
"abstract", "assert", "boolean", "break", "byte",
"case", "catch", "char", "class", "const",
"continue", "default", "do", "double", "else",
"enum", "extends", "false", "final", "finally",
"float", "for", "goto", "if", "implements",
"import", "instanceof", "int", "interface", "long",
"native", "new", "null", "package", "private",
"protected", "public", "return", "short", "static",
"strictfp", "super", "switch", "synchronized", "this",
"throw", "throws", "transient", "true", "try",
"void", "volatile", "while" , "string", "int"
}));
public static boolean isKeyword(String toCheck){
return getKeywords().contains(toCheck);
}//End isKeyword()
public static String[] getAsArray(){
return getKeywords().toArray(new String[getKeywords().size()]);
}//End getAsArray()
public static ArrayList<String> getAsArrayList(){
return new ArrayList(getKeywords());
}//End getAsArrayList()
public static HashSet<String> getAsHashSet(){
return getKeywords();
}//End getAsHashSet()
public static HashSet<String> getKeywords() {
return keywords;
}//End getKeywords
public boolean containsKeyword(String toCheck){
toCheck = toCheck.toLowerCase(); //<<<<<<<<<<<<<<<<<<<<<<< this line had been detected as error of null-pointer-exception
for(String keyword : keywords){
if(toCheck.equals(keyword) || toCheck.endsWith("." + keyword) ||
toCheck.startsWith(keyword + ".") || toCheck.contains("." + keyword + ".")){
return true;
}//End if
}//End for
return false;
}//End containsKeyword()
}//End JavaKeywords
这就是所有的代码!!我的其他类只是图形用户界面类,与数据存储无关,所以我想我不应该发布它们。感谢您阅读我的问题,如果您有任何想法,请帮助:(
解决方案
您可以通过阅读堆栈跟踪来发现问题:
- 创建
LJKeywords
的实例时出现问题(由在LJKeywords.<init>
(LJKeywords.Java:10)消息创建)。 - 创建
LAddClass
(通过在LAddClass.<init>
(LAddClass.java:8)消息)的实例时发生的错误。 - 创建
LStore
类的实例时(通过atLStore.<init>
(LStore.java:9)消息)。
然后,通过检查LAddClass
和LStore
类构造函数和字段,我发现:
public class LAddClass{
LJKeywords keyObject = new LJKeywords();
LStore stObject = new LStore(className, methodName,isPrivate);
//...
}
public class LStore {
LAddClass classObject = new LAddClass();
//...
}
那么,这是做什么的?当您创建LStore
对象引用时,它将在内部创建LAddClass
对象引用,该对象引用将在内部创建新的LStore
对象引用,该对象引用将在内部创建LAddClass
对象引用。好了,现在您知道这是怎么回事了,这里有一个无限对象实例化循环。
如何解决此问题?移除这个无限循环后,您可以通过在客户端类中分离和关联来创建LAddClass
和LStore
。例如:
class Client {
void foo() {
LAddClass lAddClass = new LAddClass();
LStore lStore = new LStore();
lStore.setLAddClass(lAddClass);
lAddClass.setLStore(lStore);
//...
}
}
此外,我建议将您的类的名称更改为更重要的名称。例如,用LStore
代替Storage
,用LAddClass
代替UMLClass
(或更合适的名称)。
相关文章