views:

93

answers:

3

I have two similar methods. One is intended to handle objects, the other vectors:

@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); 
            }
}

If I understand Java and polymorphism correctly, if a call the method with a vector, the first function should be called, but if I call it with anything else which is an object, the second method should be called.

However, when my program goes to call the function, somehow it is getting the wrong one because instead of processing correctly, I get this:

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...

If I understand the stacktrace correctly, it is telling me that it is failing because dataOb is a vector, but if this is true, shouldn't the other method have caught the call?

Did I misunderstand something about Java's polymorphism? Should something in the signature be different? Do I really need to check whether the object is an instance of vector before calling that specific function, instead of relying on polymorphism to handle the distinction? Is there a good way to fix this problem from within one or the other of the printRows() methods?

+3  A: 

You haven't provided quite enough info, so I am guessing a bit... if what I am saying here doesn't apply please let me know. It would be useful to the the code that calls printRows...

If you do this:

Object x = new Vector();

printRows(..., x);

then the printRows(..., Object) method will be called because the resolution of what method to call is done at compile time not runtime. The compiler decides what method to call based on the type of the variable is declared. At no time, when choosing what method to call, does anything look at the value that is in the object.

You can fix this putting code like this at the top of the printRows(..., Object) method:

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

This is similar to this question.

TofuBeer
I think the array cast is causing the problem
Bozho
The printRows(..., Vector) doesn't cast to Object[] though... which is what the OP wants to have called.
TofuBeer
@TofuBeer - Cheers for the response. The true history of the value getting passed is somewhat more convoluted, but in a nutshell, it seems that my code boils down to that. The original code for the servlet this code comes from actually used instanceof to handle this without the seperate function calls... I thought I would be clever by moving the blocks out and letting polymorphism take care of seperating the cases ... but I now see it doesn't complete work that way. Cheers for the clarification why!
Brian Kessler
+3  A: 

Did I misunderstand something about Java's polymorphism?

Yes. Overloaded methods are not subject to runtime polymorphism, only overriden methods. The choice between your methods happens at compile time according to the declared type of the reference you pass into the method.

Michael Borgwardt
Cheers for the feedback. :-)
Brian Kessler
A: 

Are you sure that you call the method with a Vector? can you show us the call?

Torres
@Torres - See Tofu's answer above... It pretty accurately summarizes the situation. If you want to see the entire code, I can post it, but its much longer and full of useless details. :-)
Brian Kessler