[英]Java Class Cast Exception
我现在正在从事的项目涉及到我从文本文件中读取单词并将它们加载到数组中(最终是一个二叉树,但这将在以后完成)。 我必须将单词和单词的频率(最初为1)都加载到数组中,因此我已经将两个变量都打包到对象WordNode
。 我能够将单词加载到数组中,但是当我尝试检查单词是否已在数组中时,事情就崩溃了。 如果是这样,我必须将频率增加1。我编写了一个新的equals()
方法来覆盖默认方法,以便比较单词而不是变量引用。 但是,我现在Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LWordNode;
得到错误Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LWordNode;
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LWordNode;
。 为什么会这样? 我以为只有WordNode
对象被传递给equals()
。
主要方法:
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类:
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;
}
}
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;
}
一种可能的原因是您的equals
方法:
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));
}
如果obj不是WordNode,将抛出异常。
您应该看一下有关Java应该如何重写equals和hashcode的讨论 。
使用泛型时,Java 会删除类型信息并在运行时执行强制类型转换。 这意味着,如果您的代码的任何部分包含T[]
,则它将编译为Object[]
。
基于对wordArray.list[index].setFrequency()
和wordArray.list[index].getFrequency()
,您似乎wordArray.list[index].getFrequency()
T[]
用作ArrayUnorderedList的list
字段的类型。 这不是泛型的正确使用。 Java将尝试在访问数组索引之前将Object[] list
WordNode[]
为WordNode[]
。 将一种数组类型转换为另一种数组类型将始终产生ClassCastException。
考虑直接在ArrayUnorderedList中实现public T get(int index)
方法,而不是直接访问list
字段。 在方法签名中使用通用类型T
是在通用集合中实现对象访问的正确方法。 在这里,隐式强制转换发生在数组访问之后。
或者,考虑改为使用java.util.ArrayList或java.util.HashSet类。 两者都是通用集合。
不要只在始终使用WordNode参数调用equals方法时使用。
您必须验证参数对象的类型
public boolean equals(Object obj) {
if(!(obj instanceof WordNone)){
return false;
}
// rest of equals method
}
绝对不能认为在equals中传递的内容始终是同一对象的实例。 你需要做一些检查
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));
}
无论如何,为什么不使用Set
呢? 这是可以用于案例的最佳数据结构。
由于您只关心单词及其频率,为什么不使用Map或Set? 关键字是单词,值是频率。 这样,您只需调用Map.contains(word),然后查看它是否已经存在,然后执行您想使用的任何操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.