2012-04-11 7 views
0

Das Projekt, an dem ich gerade arbeite, beinhaltet das Lesen von Wörtern aus einer Textdatei und das Laden von Wörtern in ein Array (und eventuell einen Binärbaum, der aber später beendet wird). Ich muss sowohl die Wort- als auch die Worthäufigkeit (anfangs 1) in das Array laden, also habe ich beide Variablen in ein Objekt WordNode gepackt. Ich kann die Wörter in das Array laden, aber die Dinge fallen auseinander, wenn ich versuche zu überprüfen, ob ein Wort bereits im Array ist. Wenn dies der Fall ist, muss ich die Häufigkeit um 1 erhöhen. Ich habe eine neue equals()-Methode geschrieben, um die Standardmethode zu überschreiben, so dass Wörter anstelle von Variablenreferenzen verglichen werden. Allerdings bekomme ich jetzt den Fehler Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LWordNode;. Warum kommt das auf? Ich dachte nur WordNode Objekte wurden an equals() übergeben.Java Class Cast Ausnahme

Main-Methode:

public class Driver { 
/////////////// fields /////////////// 
public static ArrayUnorderedList<WordNode> wordArray = new ArrayUnorderedList<WordNode>(); 
public static LinkedBinarySearchTree<WordNode> wordTree = new LinkedBinarySearchTree<WordNode>(); //tree to hold words 

/////////////// methods /////////////// 
public static void main(String[] args) throws Exception { 
    //ask for filename  
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 
    System.out.println("Enter the name of the file to read from: "); 
    Reader file = new FileReader(reader.readLine()); 

    //read file 
    Scanner input = new Scanner(file); 

    while(input.hasNext()) { 
     //get words from file 
     String word = input.next(); 

     //remove non-word characters and convert to lowercase 
     word = word.replaceAll("\\W", ""); 
     word = word.toLowerCase(); 

     //create node 
     WordNode newWord = new WordNode(word); 

     //if word is already in array 
     if(wordArray.contains(newWord)) { 
      System.out.println("Word is already in array"); 

      //increment frequency by 1 
      int index = wordArray.find(newWord); 
      wordArray.list[index].setFrequency(wordArray.list[index].getFrequency() + 1); 
      System.out.println("(" + newWord.getFrequency() + ") " + newWord.getWord()); 
     } else { 
      System.out.println("Word is not yet in array"); 

      //add word to tree 
      System.out.println("(" + newWord.getFrequency() + ") " + newWord.getWord()); 
      wordArray.addToRear(newWord); 
     } 
    } 

    //insert into tree 

    //perform traversals on tree 
} 

WordNode Klasse:

public class WordNode { 
    protected String word; 
    protected WordNode left, right; 
    protected int frequency; 

    /** 
    * Creates a new node with the specified data. 
    * @param obj the element that will become a part of the new node 
    */ 
    WordNode(String obj) { 
     word = obj; 
     left = null; 
     right = null; 
     frequency = 1; 
    } 

    /** 
    * Method to check for string equivalence. 
    * @return true if words are the same 
    */ 
    public boolean equals(Object obj) { 
     WordNode tempWord = (WordNode)obj; 
     return(tempWord.getWord().equals(this.word)); 
    } 

    /** 
    * Gets the word. 
    * @return the word 
    */ 
    public String getWord() { 
     return word; 
    } 

    /** 
    * Sets the word. 
    * @param word the word to set 
    */ 
    public void setWord(String word) { 
     this.word = word; 
    } 

    /** 
    * Gets the left. 
    * @return the left 
    */ 
    public WordNode getLeft() { 
     return left; 
    } 

    /** 
    * Sets the left. 
    * @param left the left to set 
    */ 
    public void setLeft(WordNode left) { 
     this.left = left; 
    } 

    /** 
    * Gets the right. 
    * @return the right 
    */ 
    public WordNode getRight() { 
     return right; 
    } 

    /** 
    * Sets the right. 
    * @param right the right to set 
    */ 
    public void setRight(WordNode right) { 
     this.right = right; 
    } 

    /** 
    * Gets the frequency. 
    * @return the frequency 
    */ 
    public int getFrequency() { 
     return frequency; 
    } 

    /** 
    * Sets the frequency. 
    * @param frequency the frequency to set 
    */ 
    public void setFrequency(int frequency) { 
     this.frequency = frequency; 
    } 
} 

Einige Methoden aus der Klasse Arraylist:

/** 
* Returns true if this list contains the specified element. 
* @param target the element that the list is searched for 
* @return true if the target is in the list, false if otherwise 
*/ 
public boolean contains(T target) { 
    return (find(target) != NOT_FOUND); 
} 

/** 
* Returns the array index of the specified element, or the 
* constant NOT_FOUND if it is not found. 
* @param target the element that the list will be searched for 
* @return the integer index into the array containing the target element, or the NOT_FOUND constant 
*/ 
public int find(T target) { 
    int scan = 0, result = NOT_FOUND; 
    boolean found = false; 

    if (!isEmpty()) { 
     while (!found && scan < rear) { 
      if (target.equals(list[scan])) { 
       found = true; 
      } else { 
      scan++; 
      } 
     } 
    } 

    if (found) { 
     result = scan; 
    } 

    return result; 
} 
+0

Der Fehler ist irgendwo in der 'ArrayUnorderedList' Klasse. Ein Stacktrace und der vollständige Code dieser Klasse wäre hilfreich. – trutheality

+2

Wenn Sie eine Ausnahme erhalten, meldet der Stack-Trace die Zeile, in der die Ausnahme ausgelöst wurde, wodurch der Teil des Codes reduziert wird, den Sie untersuchen müssen. – assylias

+0

Dies ist "zu lokalisiert" und SO ist keine "Code-Review-Site", aber ** es ist wie jedes andere CCE **: Sie versuchen, einen inkonvertierbaren Typ zu erzeugen. Casting * kann * und * nicht * einen Typ ändern. Es ändert nur die "statisch typisierte Ansicht" eines gegebenen Objekts. Bitte benutzen Sie auch die verfügbaren Tools zum Debuggen :( –

Antwort

1

Wenn Sie Generics, Java erases the type information verwenden, führt die Konvertierung zur Laufzeit aus. Das heißt, wenn ein Teil Ihres Codes T[] enthält, wird er stattdessen als Object[] kompiliert.

Basierend auf den Verweisen auf wordArray.list[index].setFrequency() und wordArray.list[index].getFrequency(), sieht es aus wie Sie T[] als Typ für das list Feld ArrayUnorderedList verwendet. Dies ist keine korrekte Verwendung von Generika. Java versucht, Object[] list zu WordNode[] vor dem Zugriff auf den Index des Arrays zu konvertieren. Wenn Sie einen Array-Typ in einen anderen Array-Typ umwandeln, wird immer eine ClassCastException erzeugt.

Anstatt direkt auf das Feld list zuzugreifen, können Sie eine public T get(int index)-Methode in ArrayUnorderedList implementieren. Die Verwendung des generischen Typs T in der Methodensignatur ist die geeignete Methode zum Implementieren des Objektzugriffs in einer generischen Auflistung. Hier tritt die implizite Umwandlung nach der Array-Zugriff.

Alternativ können Sie stattdessen die Klassen java.util.ArrayList oder java.util.HashSet verwenden. Beide sind generische Sammlungen.

+0

Das stimmt, 'List' ist vom Typ' T [] 'in' ArrayUnorderedList'! So wurde es im mitgelieferten Code geschrieben. Ich war mir nicht bewusst über Typ löschen, aber danke für die Info. Ich werde versuchen, eine Get-Methode dafür zu implementieren. (Schreibe ich einfach "public T get()" und dann etwas in diese Methode wie das, was ich ursprünglich geschrieben habe, wie 'this.list [index]'? Das ist mein Verständnis.) – lollercopter

+0

Ja. Wenn Sie 'list' in ein' Object [] 'geändert haben, müssen Sie das Ergebnis in den generischen Typ T umwandeln. ' public T get (int index) {' ' zurück (T) list [index ]; ' '} ' Entschuldigung für das Fehlen von Zeilenumbrüchen. – MALfunction84

4

Eine mögliche Ursache ist Ihre equals Methode:

public boolean equals(Object obj) { 
    //You need to check that obj is a WordNode 
    //For example: if (obj instanceof WordNode) {... 
    WordNode tempWord = (WordNode)obj; 
    return(tempWord.getWord().equals(this.word)); 
} 

wird eine Ausnahme auslösen, wenn obj kein WordNode ist.

Sie sollten sich this discussion about how one should override equals and hashcode in Java ansehen.

+1

+1 für die Antwort, da es das Problem lösen wird. Ich würde hinzufügen, dass er/sie sollte herausfinden, warum dieser Vergleich passiert.Ich sage nicht, dass es nicht passieren kann, aber weiter Solch einfaches Programm, es ist vielleicht ein Zeichen für einen anderen Fehler.Er könnte einen Thread-Dump hinzufügen ('neue Ausnahme (" Here * "). printStackTrace()'), wenn dies passiert –

+0

Ich habe den Stack-Trace (ich denke, das ist was war es - die Zeilennummer in der Klasse, in der der Fehler gefunden wurde?) und anscheinend ist der Fehler in der Zeile ' wordArray.list [index] .setFrequency (wordArray.list [index] .getFrequency() + 1); '. Danke, dass Sie mit mir arbeiten, ich lerne immer noch. – lollercopter

+0

Es ist schwierig zu wissen, was die Ausnahme verursacht, ohne einen vollständigen Stack-Trace (der mehr als eine Zeile enthalten muss) oder den Code von ArrayUnorderedList. – assylias

0

nicht mit Ausnahme der Equals-Methode sollte immer mit einem WordNode-Parameter aufgerufen werden.

Sie haben den Typ des Parameter-Objekts überprüfen

public boolean equals(Object obj) { 
    if(!(obj instanceof WordNone)){ 
    return false; 
    } 
    // rest of equals method 
} 
0

Es ist nie sicher davon ausgehen, dass das, was in dem Gleichheits wird immer eine Instanz des gleichen Objekts sein geben wird. Sie müssen einige Schecks wie

public boolean equals(Object obj) { 
    if (this == obj) { 
     return true; 
    } 
    if (obj == null) { 
     return false; 
    } 
    if (getClass() != obj.getClass()) { 
     return false; 
    } 
    WordNode otherWord = (WordNode) obj; 

    return(otherWord.getWord().equals(this.word)); 
} 

Wie auch immer tun, warum Sie keine Set stattdessen verwenden? Es ist die beste Datenstruktur, die Sie für Ihren Fall verwenden können.

0

Da Sie sich nur für ein Wort und seine Häufigkeit interessieren, warum verwenden Sie nicht stattdessen eine Karte oder ein Set? Der Schlüssel wäre das Wort und der Wert die Häufigkeit. Auf diese Weise rufen Sie einfach Map.contains (Wort) auf und Sie sehen, ob es bereits in und dann tun, was auch immer Sie damit machen wollen.

+0

Sorry, hab gerade das Ding mit links/rechts gesehen. – Giannis

Verwandte Themen