简体   繁体   中英

classcastexception from an introductory programmer: conversion from object to String

I have been working on a program called Deque. The program has four methods: given an arbitrary array, I can add an element to the front of the array(addFirst), to the back(addLast), remove the first element(removeFirst), and remove the last element(removeLast).

(StdIn, StdOut are API's that work the same way as in C)

Yes, the program compiles and I can add and remove items on a list. Everything works perfectly until I stop adding element and try to print out the elements on the list (I assign StdIn.isEmpty = True and break the loop; please refer to the main method.). For example, input 1 and 2 gives me the following error:

java Deque1.java
+
Type your input String addFirst: 1
++
Type your input String addLast: 2
deque[]: Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
        at Deque1.main(Deque1.java:123)

and line 123 is: StdOut.print(dequeinstance.deque[(dequeinstance.first + i) % dequeinstance.deque.length] + " ");

I have been working on this small error for several hours but all that returned was a frustration from a repeated run-time error. I believe I have declared Item to be the type String but I can't figure out why the code does not work. Help me please. This is the code that I wrote that continuously gives me classcastexception error:

import java.util.Iterator;
import java.util.NoSuchElementException;

public class Deque1<Item> implements Iterable<Item> {

    private Item[] deque;
    private int N = 0;
    private int last = 0;
    private int first = 0;

    public Deque1()                           // construct an empty deque
    {
        deque = (Item[]) new Object[2];
    }

    public boolean isEmpty()                 // is the deque empty?
    {
        return N == 0;
    }

    public int size()                        // return the number of items on the deque
    {
        return N;
    }

    public void addFirst(Item item)          // add the item to the front
    {
        if(item == null) throw new java.lang.NullPointerException();
        if(N == deque.length) resize(2 * deque.length);
        deque[first--] = item;
        if (first == -1) first = deque.length - 1;
        N++;
    }

    public void addLast(Item item)           // add the item to the end
    {
        if(item == null) throw new java.lang.NullPointerException();
        if(N == deque.length) resize(2*deque.length);
        if(last == deque.length - 1) last = -1;
        deque[++last] = item;
        N++;
    }

    public Item removeFirst()                // remove and return the item from the front
    {
        if (isEmpty()) throw new NoSuchElementException("Queue underflow");
        if(N > 0 && N == deque.length/4) resize(deque.length/2);
        if(first == deque.length - 1) first = -1;
        Item item = deque[++first];
        deque[first] = null;
        return item;
    }

    public Item removeLast()                 // remove and return the item from the end
    {
        if (isEmpty()) throw new NoSuchElementException("Queue underflow");
        if(N > 0 && N == deque.length/4) resize(deque.length/2);
        Item item = deque[last];
        deque[last--] = null;
        if(last == -1) last = deque.length -1;
        N--;
        return item;
    }

    private void resize(int capacity)
    {
        Item[] temp = (Item[]) new Object[capacity];
        for(int i = 0; i < N; i++)
        {
            temp[i] = deque[(first + i)%deque.length];
        }
        deque = temp;
        first = 0;
        last = N - 1;
    }

    public Iterator<Item> iterator() {return new ArrayIterator();}

    // an iterator, doesn't implement remove() since it's optional
    private class ArrayIterator implements Iterator<Item> {
        private int i = 1;
        public boolean hasNext()  {return i <= N;}
        public void remove()      {throw new java.lang.UnsupportedOperationException();}

        public Item next()
        {
            if (!hasNext()) throw new java.util.NoSuchElementException();
            Item item = deque[(i + first) % deque.length];
            i++;
            return item;
        }
    }

    public static void main(String[] args)
    {
        Deque1<String> dequeinstance = new Deque1();
        //String[] dq = dequeinstance.deque;
        //Iterator<String> itr = dq.iterator();
        while (!StdIn.isEmpty())
        {
            String item = StdIn.readString();
            if (item.equals("--")) dequeinstance.removeLast();
            else if (item.equals("-")) dequeinstance.removeFirst();
            else if (item.equals("++")) 
            {
                StdOut.print("Type your input String addLast: ");
                String item2 = StdIn.readString();
                dequeinstance.addLast(item2);
            }
            else if (item.equals("+")) 
            {
                StdOut.print("Type your input String addFirst: ");
                String item2 = StdIn.readString();
                dequeinstance.addFirst(item2);
            }
        }

        //for(String str : itr)
        StdOut.print("deque[]: ");
        for(int i = 1; i <= dequeinstance.size(); i++)
        {
            StdOut.print(dequeinstance.deque[(dequeinstance.first + i) % dequeinstance.deque.length] + " ");
        }

        System.out.println();
    }
}

ps. On a separate piece of note, how do I create an Iterator that iterates all elements in the list deque (String[] deque)?

When I try to create an iterator

Iterator<String> itr = dq.iterator();

I get a compile-error:

  Deque1.java:99: error: cannot find symbol
  Iterator<String> itr = dq.iterator();
                                 ^
  symbol:   method iterator()
  location: variable dq of type String[]

I tried to use an alternative by removing dq and directly referring deque in class Deque

Iterator<String> itr = dequeinstance.deque.iterator();

this time, I get a similar but different error:

Iterator<String> itr = dequeinstance.deque.iterator();
                                                  ^
symbol:   method iterator()
location: variable deque of type Item[]
where Item is a type-variable:
Item extends Object declared in class Deque1

I have added Java Generics to your code to correctly inherit from the iterator class.

I beleive the code now functions as it should do.

The ClassCastException no longer occurs, this was happening for two reasons, you were using 'dequeinstance.deque.length' instead of 'dequeinstance.size()' which isn't such a huge problem. But the big problem was the lack of the use of Java Generics which was causing Java to not understand that the following line:

dequeinstance.deque[(dequeinstance.first + i) % dequeinstance.deque.length] + " "

was actually a string.

This is why the generics are required.

See your code below.

package test;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class Deque1<E> implements Iterable<E> {

    private Object[] deque;
    private int N = 0;
    private int last = 0;
    private int first = 0;

    public Deque1()                           // construct an empty deque
    {
        deque = (Object[]) new Object[2];
    }

    public boolean isEmpty()                 // is the deque empty?
    {
        return N == 0;
    }

    public int size()                        // return the number of items on the deque
    {
        return N;
    }

    public void addFirst(Object item)          // add the item to the front
    {
        if(item == null) throw new java.lang.NullPointerException();
        if(N == deque.length) resize(2 * deque.length);
        deque[first--] = item;
        if (first == -1) first = deque.length - 1;
        N++;
    }

    public void addLast(Object item)           // add the item to the end
    {
        if(item == null) throw new java.lang.NullPointerException();
        if(N == deque.length) resize(2*deque.length);
        if(last == deque.length - 1) last = -1;
        deque[++last] = item;
        N++;
    }

    public Object removeFirst()                // remove and return the item from the front
    {
        if (isEmpty()) throw new NoSuchElementException("Queue underflow");
        if(N > 0 && N == deque.length/4) resize(deque.length/2);
        if(first == deque.length - 1) first = -1;
        Object item = deque[++first];
        deque[first] = null;
        return item;
    }

    public Object removeLast()                 // remove and return the item from the end
    {
        if (isEmpty()) throw new NoSuchElementException("Queue underflow");
        if(N > 0 && N == deque.length/4) resize(deque.length/2);
        Object item = deque[last];
        deque[last--] = null;
        if(last == -1) last = deque.length -1;
        N--;
        return item;
    }

    private void resize(int capacity)
    {
        Object[] temp = (Object[]) new Object[capacity];
        for(int i = 0; i < N; i++)
        {
            temp[i] = deque[(first + i)%deque.length];
        }
        deque = temp;
        first = 0;
        last = N - 1;
    }

    public Iterator<E> iterator() {return (Iterator<E>) new ArrayIterator();}

    // an iterator, doesn't implement remove() since it's optional
    private class ArrayIterator implements Iterator<Object> {
        private int i = 1;
        public boolean hasNext()  {return i <= N;}
        public void remove()      {throw new java.lang.UnsupportedOperationException();}

        public Object next()
        {
            if (!hasNext()) throw new java.util.NoSuchElementException();
            Object item = deque[(i + first) % deque.length];
            i++;
            return item;
        }
    }

    public static void main(String[] args)
    {
        Deque1<String> dequeinstance = new Deque1<String>();
        //String[] dq = dequeinstance.deque;
        //Iterator<String> itr = dq.iterator();
        while (!StdIn.isEmpty())
        {
            String item = StdIn.readString();
            if (item.equals("--")) dequeinstance.removeLast();
            else if (item.equals("-")) dequeinstance.removeFirst();
            else if (item.equals("++")) 
            {
                StdOut.print("Type your input String addLast: ");
                String item2 = StdIn.readString();
                dequeinstance.addLast(item2);
            }
            else if (item.equals("+")) 
            {
                StdOut.print("Type your input String addFirst: ");
                String item2 = StdIn.readString();
                dequeinstance.addFirst(item2);
            }
        }

        //for(String str : itr)
        StdOut.print("deque[]: ");
        for(int i = 1; i <= dequeinstance.size(); i++)
        {
            StdOut.print(dequeinstance.deque[(dequeinstance.first + i) % dequeinstance.deque.length] + " ");
        }

        System.out.println();
    }
}

In answer to your second question, Your class is already an iterator. You can't make an iterator an iterator. Iterator classes provide functions such as .next() etc, you already have these, hence why you can't get these again.

When I try to create an iterator

Iterator<String> itr = dq.iterator();

I Got compile time error

 Deque1.java:99: error: cannot find symbol
  Iterator<String> itr = dq.iterator();
                                 ^
  symbol:   method iterator()
  location: variable dq of type String[]

This Compile time error is self explanatory , Since your dq is of type String[] which is not an implemented class of Collection Interface , iterator method is of Collection Interface not of String[]

As Documentation says

Iterator<E> iterator()

Returns an iterator over the elements in this collection. There are no guarantees concerning the order in which the elements are returned (unless this collection is an instance of some class that provides a guarantee).

Now coming to

On a separate piece of note, how do I create an Iterator that iterates all elements in the list deque (String[] deque)?

Firstly List and Array are not the Same ,

private Item[] deque; // can not Iterate with Iterator
private List<Item> deque;//Iterate this with an Iterator since it is a List

if You want to Iterate the Array with the help of iterator , then use this

Arrays.asList(deque).iterator();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM