【Java】可比较泛型建数组传递报强转类型错误解决方案
问题
可比较泛型怎么新建数组?
自己写基于AVL树的散列表时,在自动扩容的时候需要遍历AVL树的Key,所以需要AVL树提供一个方法返回一个Key数组以遍历,初始实现如下:
/**
* 用于辅助遍历Key
*/
class KeyQueue {
private K[] queue;
private int size;
public KeyQueue(int capacity) {
queue = (K[]) new Object[capacity];
size = 0;
}
public void enQueue(K key) {
queue[size] = key;
size++;
}
public Object[] getQueue() {
return queue;
}
}
/**
* 返回所有键
*
* @return 键数组
*/
public Object[] getKeyArray() {
KeyQueue queue = new KeyQueue(size);
preOrder(root, queue);
return queue.getQueue();
}
private void preOrder(Node node, KeyQueue queue) {
if (node == null) {
return;
}
queue.enQueue(node.key);
preOrder(node.left, queue);
preOrder(node.right, queue);
}
KeyQueue 类是用于辅助装载Key的,因为自带的数组你不知道它装多少了,所以在此基础上简单封装了一个size变量。
但是这样会报错:
"C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.5\jbr\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.5\lib\idea_rt.jar=13543:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.5\bin" -Dfile.encoding=UTF-8 -classpath D:\Project\DataStructureJavaLearn2021\out\production\data_structure_java top.minuy.structure.hash.Test
Test AVLTreeHashTable :
Exception in thread "main" java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.Comparable; ([Ljava.lang.Object; and [Ljava.lang.Comparable; are in module java.base of loader 'bootstrap')
at top.minuy.structure.map.AVLTreeMap$KeyQueue.<init>(AVLTreeMap.java:59)
at top.minuy.structure.map.AVLTreeMap.getKeyArray(AVLTreeMap.java:79)
at top.minuy.structure.hash.AVLTreeHashTable.resize(AVLTreeHashTable.java:214)
at top.minuy.structure.hash.AVLTreeHashTable.add(AVLTreeHashTable.java:92)
at top.minuy.structure.hash.AVLTreeHashTable.add(AVLTreeHashTable.java:10)
at top.minuy.structure.hash.Test.testHashTable(Test.java:61)
at top.minuy.structure.hash.Test.main(Test.java:21)
Process finished with exit code 1
然后到网上看看有没有可以new一个可比较对象数组,发现好像并没有。
只能放弃这个想法。
解决
后来想了下,数组其实也是一种类,还不知道哪里有关于可比较泛型数组这方面的内容介绍,个人猜测转不了的原因应该是它们两个数组类Object[] 和 K[] 没有继承关系,但是想了下,它们里面的元素有继承关系。所以应该是在元素级别强转,而不是数组级别。
所以AVLTreeMap中的改为:
/**
* 用于辅助遍历Key
*/
class KeyQueue {
private Object[] queue;
private int size;
public KeyQueue(int capacity) {
queue = new Object[capacity];
size = 0;
}
public void enQueue(Object key) {
queue[size] = key;
size++;
}
public Object[] getQueue() {
return queue;
}
}
/**
* 返回所有键
*
* @return 键数组
*/
public Object[] getKeyArray() {
KeyQueue queue = new KeyQueue(size);
preOrder(root, queue);
return queue.getQueue();
}
private void preOrder(Node node, KeyQueue queue) {
if (node == null) {
return;
}
queue.enQueue(node.key);
preOrder(node.left, queue);
preOrder(node.right, queue);
}
就返回Object数组
但是AVLTreeHashTable这边因为类型原因报错了
/**
* 重新分配散列表大小
*
* @param capacity 新的散列表大小
*/
private void resize(int capacity) {
// System.out.println("resize : " + capacity + " size : " + size);
AVLTreeMap<K, V>[] newTable;
newTable = new AVLTreeMap[capacity];
for (int i = 0; i < newTable.length; i++) {
newTable[i] = new AVLTreeMap<>();
}
K[] keyArray;
for (int i = 0; i < table.length; i++) {
AVLTreeMap<K, V> map = table[i];
keyArray = (K[])map.getKeyArray();
for (int j = 0; j < keyArray.length; j++) {
// System.out.println("["+j+"]"+keyArray[j] + " ");
int hash = getHash(keyArray[j]);
newTable[hash].add(keyArray[j], map.get(keyArray[j]));
}
// System.out.println();
// System.out.println("index : " + i);
}
table = newTable;
}
这句:
keyArray = (K[])map.getKeyArray();
也是一样的错误,我们应该从数组中取出元素后再强转。
所以修改为:
/**
* 重新分配散列表大小
*
* @param capacity 新的散列表大小
*/
private void resize(int capacity) {
// System.out.println("resize : " + capacity + " size : " + size);
AVLTreeMap<K, V>[] newTable;
newTable = new AVLTreeMap[capacity];
for (int i = 0; i < newTable.length; i++) {
newTable[i] = new AVLTreeMap<>();
}
Object[] keyArray;
for (int i = 0; i < table.length; i++) {
AVLTreeMap<K, V> map = table[i];
keyArray = map.getKeyArray();
for (int j = 0; j < keyArray.length; j++) {
// System.out.println("["+j+"]"+keyArray[j] + " ");
K key = (K) keyArray[j];
int hash = getHash(key);
newTable[hash].add(key, map.get(key));
}
// System.out.println();
// System.out.println("index : " + i);
}
table = newTable;
}
其中这句:
K key = (K) keyArray[j];
就是在元素从数组中取出后才强转,因为运行时它原本就是AVLTreeMap那边返回的K类型的元素,所以可以强转成功~
至此,问题解决~~
【Java】可比较泛型建数组传递报强转类型错误解决方案的更多相关文章
- 【java】泛型的作用是在编译阶段防止错误输入,绕过编译就绕过泛型,可用反射验证
package com.tn.collect; import java.lang.reflect.Method; import java.util.ArrayList; public class Fa ...
- jmeter发送json数据,报405、400错误解决方案
1.405错误解决方案:添加HTTP信息头管理器(错误因数:发送格式未设置) 2.400错误解决方案:json文本格式有误(注意:换行.空格等)解决方案:对照json文本数据(错误因数:发送的json ...
- Java基础 - 泛型详解
2022-03-24 09:55:06 @GhostFace 泛型 什么是泛型? 来自博客 Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了&quo ...
- 跟着刚哥梳理java知识点——泛型(十三)
一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: public class GenericTest { public static void main(String[] a ...
- Java“禁止”泛型数组
Java“禁止”泛型数组 原文:https://blog.csdn.net/yi_Afly/article/details/52058708 1. 泛型定义泛型编程是一种通过参数化的方式将数据处理与数 ...
- Java 泛型 五:泛型与数组
简介 上一篇文章介绍了泛型的基本用法以及类型擦除的问题,现在来看看泛型和数组的关系.数组相比于Java 类库中的容器类是比较特殊的,主要体现在三个方面: 数组创建后大小便固定,但效率更高 数组能追踪它 ...
- Java泛型与数组深入研究
Java中的泛型与数组平时开发用的很多,除了偶尔遇到"NullPointerException"和"IndexOutOfBoundsException"一般也不 ...
- 《徐徐道来话Java》(2):泛型和数组,以及Java是如何实现泛型的
数组和泛型容器有什么区别 要区分数组和泛型容器的功能,这里先要理解三个概念:协变性(covariance).逆变性(contravariance)和无关性(invariant). 若类A是类B的子类, ...
- Java层与Jni层的数组传递(转)
源:Java层与Jni层的数组传递 Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的S ...
- Android开发实践:Java层与Jni层的数组传递
转载:http://www.linuxidc.com/Linux/2014-03/97561.htm Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是 ...
随机推荐
- 新一代python版本与依赖管理工具 uv
uv python版本与依赖管理 选择原因 1. 新的好玩.rust开发的执行速度快 2. 确实方便 3. 轻,软件就十几二十兆,占磁盘小 4. uv.lock可以锁版本 场景应用 场景一 从 ana ...
- CDS标准视图:安排维护计划的调用 I_MAINTENANCEPLANSCHEDULE
视图名称:安排维护计划的调用 I_MAINTENANCEPLANSCHEDULE 视图类型: 视图代码: 点击查看代码 @AbapCatalog.compiler.compareFilter: tru ...
- CDS标准视图:优先级描述数据 I_GenericPriorityTextData
视图名称:优先级描述数据 I_GenericPriorityTextData 视图类型:基础视图 视图代码: 点击查看代码 @AbapCatalog.sqlViewName: 'IGENPRIOTEX ...
- winform 引用AForge调用摄像头拍照
Nuget安装这个2个: AForge.Controls; AForge.Video.DirectShow; code: namespace WindowsFormsApp1 { partial cl ...
- Java8新特性时间日期库
Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理.同样的,如果你现在依旧在项目中使用传统Date.Calendar和SimpleDateFormat等API ...
- Event Store-其它存储
背景 ENode是一个CQRS+Event Sourcing架构的开发框架,Event Sourcing需要持久化事件,事件可以持久化在DB,但是DB由于面向的是CRUD场景,是针对数据会不断修改或删 ...
- w3cschool-Hibernate 教程
什么是 ORM? ORM 表示 Object-Relational Mapping (ORM),是一个方便在关系数据库和类似于 Java, C# 等面向对象的编程语言中转换数据的技术.一个 ORM 系 ...
- 第三届全国高校计算机能力挑战赛-C
单项选择题 1.题 (3.0分) 以下叙述正确的是(). A.在C程序,至少要包含一个库函数 B.C程序的一行可以写多条语句 C.对一个C程序进行编译就可以生成可执行文件 D.C程序中的注释只 ...
- 平滑升级mariadb
问题 Centos7自带的MariaDB版本是5.5 ,版本过于老旧,现想升级到最新版本,且数据不丢失 措施 备份原来的数据 mysqldump -u root -p --all-databases ...
- ABC224
ABC224 D 题目大意 有一个九个点的无向图棋盘,上面有八个棋子,一次操作能将一个棋子沿边移到空点上,问将每个棋子移到与它编号相同的点最少几步. 解题思路 考虑使用 BFS. 用 string 存 ...