servlet和stacktrace引发Java问题

| 在以下内容中,我必须编写一个具有年龄,婚姻状况,家庭收入和孩子数量的servlet,然后转到数据库,然后将更新后的平均值返回给用户。但是,我遇到此堆栈跟踪:
java.lang.NullPointerException
    at HouseSurvey$SurveyResults.access$200(HouseSurvey.java:86)
    at HouseSurvey.doPost(HouseSurvey.java:43)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
    at org.apache.catalina.servlets.InvokerServlet.serveRequest(InvokerServlet.java:419)
    at org.apache.catalina.servlets.InvokerServlet.doPost(InvokerServlet.java:169)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:868)
    at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:663)
    at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
    at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
    at java.lang.Thread.run(Unknown Source)
这到底意味着什么?我以为我要ѭ1,但是我看不到哪里。这是我的编:
import java.text.DecimalFormat;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HouseSurvey extends HttpServlet
{
    private final static String SURVEY_FILE = \"HouseSurvey.dat\";
    SurveyResults results;
    Household h;
    DecimalFormat form = new DecimalFormat(\"#,###,#00.00\");

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        PrintWriter out = response.getWriter();  //make a printwriter to print the page
        File survey = new File(SURVEY_FILE);
        if(!survey.exists())    //check to see if the file exists
            results = new SurveyResults();
        else   
        {     //If the file exists, read it the latest survey tallies
            try
            {
                ObjectInputStream ips = new ObjectInputStream(new FileInputStream(survey));
                results = (SurveyResults)ips.readObject(); //read the file into \'results\'
                ips.close();   //close the input stream
            }
            catch(ClassNotFoundException e) {e.printStackTrace();}
            catch(FileNotFoundException f)  {f.printStackTrace();}
            catch(IOException ioe)          {ioe.printStackTrace();}
        }
        int       ageValue = Integer.parseInt(request.getParameter(\"age\")),
        childValue = Integer.parseInt(request.getParameter(\"children\"));
        double incomeValue = Double.parseDouble(request.getParameter(\"income\"));
        Boolean marriedValue = true;
        if (request.getParameter(\"status\").equals(\"married\"))
            marriedValue = true;
        else 
           if(request.getParameter(\"status\").equals(\"single\"))
           marriedValue = false;
        Household h = new Household(ageValue,childValue,incomeValue,marriedValue);
        results.totalResults(h);
        //Write results to disk.
        try
        {
            ObjectOutputStream ops = new ObjectOutputStream(new FileOutputStream(survey));
            ops.writeObject(results); ops.flush(); ops.close();
        }
        catch(IOException ioe)          {ioe.printStackTrace();}
        response.setContentType(\"text/html\");       //contnent type for the responding webpage
            out.println(\"<html>\\n\"+
                \"<head><title>Thanks!</title></head>\"+
                \"<body style=\'background:cyan;\'>\"+
                \"   <h1 style=\'text-align:center\'>RRC BIT Department - Household Survey</h1>\"+
                \"   <hr><br/>\"+
                \"   <h2 style=\'text-align:center\'>Up to Date Survey Results</h2>\"+
                \"   <h4 style=\'margin-left:200px\'>Average Age: \"+form.format(results.getAvgAge())+\"</h4>\"+
                \"   <h4 style=\'margin-left:200px\'>Average Number of Children: \"+form.format(results.getAvgKids())+\"</h4>\"+
                \"   <h4 style=\'margin-left:200px\'>Average Number of Married Respondents: \"+form.format(results.getTotalMarried())+\"</h4>\"+
                \"   <h4 style=\'margin-left:200px\'>Average Number of Single Respondents: \"+form.format(results.getTotalSingle())+\"</h4>\"+
                \"   <h4 style=\'margin-left:200px\'>Average Income: \"+form.format(results.getAvgIncome())+\"</h4></body>\");
    }                           
    private class Household
    {
        private int age, children;
        private double income;
        private boolean married=false;
        /**Method: Household
         * Constructor
         * @ param age - age of person surveyed:int
         * @ param children - number of children person surveyed has:int
         * @ param married - true or false, used to determine married or single:boolean
         * @ param income - the family income of the person surveyed:double
         */
        private Household(int age, int children, double income, boolean married)
        {
            this.age=age; this.children=children; this.income=income; this.married=married;       
        } 
        //Getters
        private int getAge()         {return age;}
        private int getChildren()    {return children;}
        private double getIncome()   {return income;}
        private boolean getMarried() {return married;}
    }
    private class SurveyResults implements Serializable
    {
        private double totalAge, totalChildren, totalMarried, totalSingle, totalIncome;
        /**Method: SurveyResults
         * Used for totals
         * @ param h - Household object created above:Household
         */      
        private void totalResults(Household h)
        {
            totalAge += h.getAge(); totalChildren += h.getChildren(); totalIncome += h.getIncome();            
            if(h.getMarried()) totalMarried += 1;
               else
                  totalSingle += 1;
        }
        private double getTotalHouseholds() {return totalSingle + totalMarried;}
        private double getAvgAge()          {return totalAge/getTotalHouseholds();}
        private double getAvgKids()         {return totalChildren/getTotalHouseholds();}
        private double getTotalMarried()    {return totalMarried;}
        private double getTotalSingle()     {return totalSingle;}
        private double getAvgIncome()       {return totalIncome/getTotalHouseholds();}
    }
}
最初在我的HTML输出中,我不小心碰到了
\"Average Number of Married Respondents: \"+form.format(results.getTotalMarried())+\"</h4>\" 
\"Average Number of Married Respondents: \"+form.format(results.getAvgKids())+\"</h4>\"
而且效果很好。然后我将其切换到前者以获取totalMarried,现在它给了我例外。问题出在哪里? 提前致谢。
已邀请:
我将其添加为单独的答案,因为它是完全不同的思路。如果最好进行编辑,请告诉我,我将删除重复的内容。 似乎在读取结果对象时会抛出
IOException
。原因是,您尝试序列化的类无法序列化。由于
SurveyResults
是一个内部类,要进行序列化,它还必须序列化包含的类(在本例中为Servlet)。我建议将您的类更改为静态嵌套类,或者可能是默认范围内的顶级类。 (根据需要更改方法访问级别。) 您可能还需要删除调查结果数据文件并重新开始。在我的测试中,它引用了不可序列化的类,并且直到将其删除后,我才能使代码运行。
我没有亲自使用
ObjectInputStream
API,但我只看到列出的
NullPointerException
有几种可能。以下行是否有可能返回null:
results = (SurveyResults)ips.readObject();
我不确定
readObject
是否会返回null,或者如果无法读取该对象是否会抛出异常。 另一种可能性是,在加载结果对象之前会引发异常。您有3个空的catch块仅打印异常-它们正在执行吗? (换句话说,您是否看到其他异常被抛出?) 除此之外,有可能会得到一个空指针,将您的布尔值拆箱成布尔值(就像您对riedValue一样),尽管在列出的代码中我看不到这种可能性。
HouseSurvey$SurveyResults.access$200()
是编译器生成并插入到内部类中的综合访问器方法,以允许封闭的类(此处为,12ѭ)调用内部类的私有方法。我承认我还没看到see1的来源。 另外,您是否已确定
Household
SurveyResults
是否应为内部类(如它们当前的样子)而不是静态嵌套类,并且使它们成为静态嵌套类是否会改变情况?关于内部嵌套类与静态嵌套类的此类SO问题可能会帮助您做出决定。 更新: 我尝试将其制作为独立类(仅显示所做的更改):
public class HouseSurvey
{
    public static void main(String[] args) {
        HouseSurvey h = new HouseSurvey();
        h.doPost(args);
    }

 public void doPost(String[] data) throws Exception {
    PrintWriter out = new PrintWriter(System.out);
    File survey = new File(SURVEY_FILE);
    if (!survey.exists()) {
        results = new SurveyResults();
    } else {
        ObjectInputStream ips = new ObjectInputStream(new FileInputStream(survey));
        results = (SurveyResults) ips.readObject();
        ips.close();
    }

    int ageValue = Integer.parseInt(data[0]);
    int childValue = Integer.parseInt(data[1]);
    double incomeValue = Double.parseDouble(data[2]);
    boolean marriedValue = Boolean.parseBoolean(data[3]);
    Household h = new Household(ageValue, childValue, incomeValue, marriedValue);
    results.totalResults(h);

    ObjectOutputStream ops = new ObjectOutputStream(new FileOutputStream(survey));
    ops.writeObject(results);
    ops.flush();
    ops.close();

    out.println(\"Average Age: \" + form.format(results.getAvgAge()) +
            \"\\nAverage # of Children: \" + form.format(results.getAvgKids()) +
            \"\\nAverage # of Married Respondents: \" + form.format(results.getTotalMarried()) +
            \"\\nAverage # of Single Respondents: \" + form.format(results.getTotalSingle()) +
            \"\\nAverage Income: \" + form.format(results.getAvgIncome()));
    out.flush();
    out.close();
}

[snip]

}
运行此命令时,出现以下异常跟踪:
Exception in thread \"main\" java.io.NotSerializableException: HouseSurvey
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
    at HouseSurvey.doPost(HouseSurvey.java:36)
    at HouseSurvey.main(HouseSurvey.java:9)
尽管不是ѭ1,但它确实证明了Sean提到的序列化问题是他的答案。一旦将
Household
SurveyResults
更改为静态嵌套类而不是内部类,该异常就会消失并且程序似乎可以正常工作。

要回复问题请先登录注册