为什么Java的多态性在对象和向量之间进行选择时无法捕获正确的方法?

我有两种类似的方法.一个用于处理对象,其他向量:

@SuppressWarnings("unused")
private void printRows(PrintWriter out, Vector<?> dataOb, 
        String[] columns, String[] columnType, 
        Hashtable<?, ?> columnAccessors, 
        String trOptions, String tdOptions)
    throws ServletException 
{
    System.out.println("At Printing Rows, Vector...");
    // If the object is a vector, loop through the elements.
        Vector<?> v = (Vector<?>) dataOb;
        Enumeration<?> e = (Enumeration<?>) v.elements();
        while (e.hasMoreElements())
        {
            tryRow(out, e.nextElement(), 
                        columns, columnType, columnAccessors, trOptions, tdOptions);
        }
}

private void printRows(PrintWriter out, Object dataOb, 
        String[] columns, String[] columnType, 
        Hashtable<?, ?> columnAccessors, 
        String trOptions, String tdOptions) 
    throws ServletException 
{
    System.out.println("At Printing Rows, Object...");
    // If the object is an array, loop through the objects.
        Object[] objects = null;
        try {objects = (Object[]) dataOb;}
        catch (Exception e1) { ExceptionToolkit.exceptionHandler (e1, "Can't assign data to objects"); }

        System.out.println("At Printing Rows, have objects...");
        for (Object object: objects)
            {
                System.out.println("At Printing Rows, have objects, looping...");
                tryRow(out, object, columns, columnType, columnAccessors, trOptions, tdOptions); 
            }
}

如果我正确理解Java和多态,如果使用向量调用方法,则应调用第一个函数,但如果我用其他任何对象调用它,则应调用第二个方法.

但是,当我的程序去调用该函数时,不知何故它得到了错误的一个,因为而不是正确处理,我得到这个:

CLASS: class hu.flux.models.PersonColumn: name
CLASS: class hu.flux.models.PersonColumn: phone
At Printing Rows, Object...
Can't assign data to objects: java.lang.ClassCastException: java.util.Vector cannot be cast to [Ljava.lang.Object;
java.lang.ClassCastException: java.util.Vector cannot be cast to [Ljava.lang.Object;
    at hu.flux.tables.TableServlet.printRows(TableServlet.java:97)
    at hu.flux.tables.TableServlet.service(TableServlet.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:674)
    at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:579)
    at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:516)
    at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:930)
    at org.apache.jsp.ShowPeople_jsp._jspService(ShowPeople_jsp.java:68)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:68)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:376)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:674)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:462)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:401)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:329)
    at hu.flux.ControllerServlet.gotoPage(ControllerServlet.java:84)
    at hu.flux.ControllerServlet.service(ControllerServlet.java:47)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:243)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:201)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:163)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:108)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:556)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:401)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:242)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:267)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:245)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:260)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:619)
At Printing Rows, have objects...

如果我正确理解了堆栈跟踪,它告诉我它是失败的,因为dataOb是一个向量,但是如果这是真的,那么其他方法是否应该捕获该调用?

我是否误解了Java的多态性?签名中的某些内容应该有所不同吗?在调用特定函数之前,我是否真的需要检查对象是否是向量的实例,而不是依靠多态来处理区别?有没有一种很好的方法可以从printRows()方法中的一个或另一个中解决这个问题?

解决方法:

你没有提供足够的信息,所以我猜一点……如果我在这里说的不适用请告诉我.调用printRows的代码会很有用……

如果你这样做:

Object x = new Vector();

printRows(..., x);

然后将调用printRows(…,Object)方法,因为要调用的方法的解析是在编译时而不是运行时完成的.编译器根据声明的变量类型决定调用哪个方法.在选择要调用的方法时,任何时候都不会查看对象中的值.

您可以在printRows(…,Object)方法的顶部修复此类推送代码:

if(x instanceof Vector)
{
    printRows(out, (Vector)dataOb);
}
else
{
   ....
}

这类似于this question.

上一篇:Java中的枚举和多态,扑克牌示例


下一篇:动态方法调度如何在Java中工作