未知的StackOverFlow错误,可能与类对象ArrayList&数据存储

时间:2013-10-27 09:10:00

标签: java stack-overflow

这是我得到的错误代码:

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)

以下是上面提到的三个类。很抱歉发布了几乎整个程序的代码,但我真的不知道错误在哪里。错误代码所产生的三条线在下面突出显示。

这是一个UML-toJava转换程序。用户必须输入类名和类类型(公共/私有),并将变量存储在虚拟类中。我已经创建了一个类对象的ArrayList来存储用户的输入,String className和boolean isPrivate。之后,必须在GUI窗口中打印类名和类型,以便用户复制文本。

我猜错误与未能将值String className, String classMethod, boolean isPrivate)存储到ArrayList<LStore>无关,而stackOverFlow是LStore类对象的arrayList。我之前有一个Null Pointer Exception错误,它应该与arraylist有关,在我更改了一些代码和类名后,我遇到了这个新的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 +"{\n"+"\t"+methodName+"\t\n}"+"}"); return javaCode; } }

的类
GuiAddClass

这里是GUI类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. " + "\nEntered name should not contain java keywords or equal to other existing names. " + "\nPlease 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

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 最初来自How to check if the class name is valid?,这是一个用于检查className是否等于java保留关键字的方法的类。它也可能与错误有关,因为这个类似乎经常被检测为错误

{{1}}

这就是所有代码!我的其他类只是GUI类,与数据存储无关,所以我想我不应该发布它们。感谢您阅读我的问题,如果您有任何想法,请帮助:(

2 个答案:

答案 0 :(得分:1)

您可以通过阅读stacktrace找到问题:

  • 创建LJKeywords的实例时遇到问题(通过 at LJKeywords.<init>(LJKeywords.java:10)消息)。
  • 在创建LAddClass的实例时(通过 at LAddClass.<init>(LAddClass.java:8)消息)会发生这种情况。
  • 在创建LStore类的实例时(通过 at LStore.<init>(LStore.java:9)消息)会发生这种情况。

然后,通过检查您的LAddClassLStore类构造函数和字段,我发现了这一点:

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对象引用,在内部...好的,现在你看到它的去向,这里有一个无限的对象实例化循环。

要解决这个问题怎么办?删除此无限循环后,您可以单独创建LAddClassLStore,并在客户端类中相互关联。例如:

class Client {
    void foo() {
         LAddClass lAddClass = new LAddClass();
         LStore lStore = new LStore();
         lStore.setLAddClass(lAddClass);
         lAddClass.setLStore(lStore);
         //...
    }
}

另外,我建议将类的名称更改为更重要的名称。例如,使用LStore代替Storage,而不是LAddClass使用UMLClass(或更合适的名称)。

答案 1 :(得分:1)

问题在于,为了创建LStore实例,您需要创建LAddClass - 并且为了创建LAddClass实例,您需要创建一个LStore实例。所以一个构造函数正在有效地调用另一个,它正在调用第一个,等等。LJKeywords类在这里是一个红色的鲱鱼,我认为 - 只是当一个新的{LJKeywords构造函数被调用时1}}实例已经创建,这恰好是打破骆驼背部的稻草。

从根本上说,您需要弄清楚希望LAddClassLStore之间的关系如何发挥作用。他们无法像这样无条件地相互建构。

我也强烈建议你摆脱所有这些类名的LAddClass前缀。