[英]Java Generic Array Class Cast Exception
我正在使用以下方法創建一棵樹 map class 以獲取值數組:
@SuppressWarnings("unchecked")
public V[] values() {
V[] values = (V[]) new Object[size()];
//System.out.println(values.getClass().getName());
return values(root, 0, values);
}
現在,當我嘗試訪問此數組中的一個元素時,我得到一個 Class Cast Exception。
private AVLTreeMap<Integer, Integer> rankingMap;
...
System.out.println(rankingMap.values()[0]); //Exception on this line
產量
Exception in thread "main" java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.Integer;
誰能解釋為什么會發生這種情況以及如何解決?
謝謝。
編輯:這是整個樹 map class
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
public class AVLTreeMap<K extends Comparable<K> , V> implements /*Map<K, V>,*/ Serializable{
private AVLTreeNode<K, V> root;
private int size;
public AVLTreeMap(){
root = null;
size = 0;
}
public int size(){
return size;
}
public void add(K key, V val){
root = insert(key, val, root);
size++;
}
private AVLTreeNode<K, V> insert(K key, V val, AVLTreeNode<K, V> currNode){
//AVLTreeNode<K, V> node = new AVLTreeNode<>(key, val);
if(currNode == null) {
return new AVLTreeNode<K, V>(key, val);
}else if(currNode.key.compareTo(key) > 0){
currNode.left = insert(key, val, currNode.left);
}else if(currNode.key.compareTo(key) < 0) {
currNode.right = insert(key, val, currNode.right);
}else if(currNode.key.compareTo(key) == 0) {
currNode.addDup(val);
}
updateNode(currNode);
return rebalance(currNode);
}
private int balanceFactor(AVLTreeNode<K, V> node) {
if(node.left == null && node.right == null){
return 0;
}else if(node.left == null){
return -node.right.height;
}else if(node.right == null){
return node.left.height;
}else {
return node.left.height - node.right.height;
}
}
private AVLTreeNode<K, V> rotateRight(AVLTreeNode<K, V> node){
AVLTreeNode<K, V> swapNode = node.left;
node.left = swapNode.right;
swapNode.right = node;
updateNode(node);
updateNode(swapNode);
return swapNode;
}
private AVLTreeNode<K, V> rotateLeft(AVLTreeNode<K, V> node){
AVLTreeNode<K, V> swapNode = node.right;
node.right = swapNode.left;
swapNode.left = node;
updateNode(node);
updateNode(swapNode);
return swapNode;
}
private void updateNode(AVLTreeNode<K, V> node){
if(node.left == null && node.right == null){
node.height = 1;
node.size = 1;
}else if(node.left == null){
node.height = node.right.height + 1;
node.size = node.right.size + 1;
}else if(node.right == null){
node.height = node.left.height + 1;
node.size = node.left.size + 1;
}else {
node.height = Math.max(node.left.height, node.right.height) + 1;
node.size = node.left.size + node.right.height + 1;
}
}
private AVLTreeNode<K, V> rebalance(AVLTreeNode<K, V> node) {
if (balanceFactor(node) < -1) {
if (balanceFactor(node.right) > 0) {
node.right = rotateRight(node.right);
}
node = rotateLeft(node);
}
else if (balanceFactor(node) > 1) {
if (balanceFactor(node.left) < 0) {
node.left = rotateLeft(node.left);
}
node = rotateRight(node);
}
return node;
}
public String tree(){
return tree(root, 0, false);
}
private String tree(AVLTreeNode<K, V> node, int tabs, boolean left){
String s = "\n";
for (int i = 0; i < tabs - 1; i++) {
s+=" ";
}
s += "----";
if(node.left == null && node.right == null){
return s + "|" + node.toString();
}else if(node.left == null){
return s + " |null" + s + "|" + node.toString() + "|" + tree(node.right, tabs + 1, false);
}else if(node.right == null){
return tree(node.left, tabs + 1, true) + s + "|"+ node.toString() + "|" + s+ " |null";
}
return tree(node.left, tabs + 1, true) + s + "|"+ node.toString() +"|" + tree(node.right, tabs + 1, false);
}
@SuppressWarnings("unchecked")
public K[] keys() {
K[] keys = (K[]) new Comparable[size()]; //https://stackoverflow.com/questions/34827626/cannot-be-cast-to-ljava-lang-comparable
return keys(root, 0, keys);
}
private K[] keys(AVLTreeNode<K, V> node, int idx, K[] keys){
if (node != null) {
keys = keys(node.left, idx, keys);
idx += (node.left != null) ? node.left.size : 0;
keys[idx++] = node.key;
for (int i = 0; i < node.dups; i++) {
keys[idx++] = node.key;
}
keys = keys(node.right, idx, keys);
}
return keys;
}
@SuppressWarnings("unchecked")
public V[] values() {
V[] values = (V[]) new Object[size()];
//System.out.println(values.getClass().getName());
return values(root, 0, values);
}
private V[] values(AVLTreeNode<K, V> node, int idx, V[] values){
if (node != null) {
values = values(node.left, idx, values);
idx += (node.left != null) ? node.left.size : 0;
values[idx++] = node.val;
addDuplicates(node, values, idx);
idx += node.dups;
values = values(node.right, idx, values);
}
return values;
}
private void addDuplicates(AVLTreeNode<K, V> node, V[] arr, int idx){
DuplicateNode<V> dup = node.nextDup;
for (int i = 0; i < node.dups; i++) {
arr[idx++] = dup.val;
dup = dup.next;
}
}
private static class AVLTreeNode<K, V>{
public int height;
public AVLTreeNode<K, V> left;
public AVLTreeNode<K, V> right;
public K key;
public V val;
public int dups;
public int size;
public DuplicateNode<V> nextDup;
public AVLTreeNode(K key, V val){
this.key = key;
this.val =val;
left = null;
right = null;
size = 1;
height = 1;
dups = 0;
nextDup = null;
}
public void addDup(V val){
DuplicateNode<V> dup = new DuplicateNode<>(val);
dup.next = nextDup;
nextDup = dup;
dups++;
size++;
}
public String toString(){
return key.toString();
}
}
private static class DuplicateNode<V>{
public V val;
public DuplicateNode<V> next;
public DuplicateNode(V val){
this.val = val;
next = null;
}
}
}
我得到一個正確值但類型不正確的數組。
您可能需要考慮為什么java.util.Collection.toArray
有兩個重載:
Object[]
T[]
,並返回一個T[]
類型的數組。原因是不可能構造一個泛型數組。 如果可能的話,第二種方法就沒有必要了。
您需要采用相同(或類似)的方法:將V[]
作為參數傳遞,您可以使用它來構造數組實例:
public V[] values(V[] array) {
// Basically, this: http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/share/classes/java/util/AbstractCollection.java#l176
V[] values = (V[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size());
//System.out.println(values.getClass().getName());
return values(root, 0, values);
}
有替代方案。 例如,您可以傳遞一個IntFunction<V[]>
(或一個V[]
,或一個V
,或一個Class<V>
):
public V[] values(IntFunction<V[]> arraySupplier) {
V[] values = arraySupplier.apply(size());
//System.out.println(values.getClass().getName());
return values(root, 0, values);
}
如果您不想將其傳遞給方法,則可以將其傳遞給構造函數,並在values()
中使用它:
public AVLTreeMap(IntFunction<V[]> arraySupplier){
this.arraySupplier = arraySupplier; // Assign to a field
}
public V[] values() {
V[] values = arraySupplier.apply(size());
// ...
}
您應該根據構建和使用 class 的繁重程度來選擇您的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.