【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[]),一个典型的应用是 ...
随机推荐
- Qwen2ForSequenceClassification文本分类实战和经验分享
本文主要使用Qwen2ForSequenceClassification实现文本分类任务. 文章首发于我的知乎:https://zhuanlan.zhihu.com/p/17468021019 一.实 ...
- .NET Core GC标记阶段(mark_phase)底层原理浅谈
简介 C# 采用基于代的回收机制,并使用了更复杂的 链式跟踪算法 来识别对象是否为垃圾. GC触发的原因 截至到.NET 8,GC触发的原因有18种 enum gc_reason { reason_a ...
- 分布式Session解决方案详解
4种分布式session解决方案 cookie和session的区别和联系 cookie是本地客户端用来存储少量数据信息的,保存在客户端,用户能够很容易的获取,安全性不高,存储的数据量小session ...
- w3cschool-Netty 实战精髓篇1
https://www.w3cschool.cn/essential_netty_in_action/ Netty 异步和数据驱动 2021-04-22 14:57 更新 在学习Netty的异步和数据 ...
- 使用pkg对nodejs项目打包
pkg的介绍可以阅读官方说明.下面针对使用做一个简单的说明. 1. 安装, 假设需要将项目打包成 win-x86 下运行的软件包,需要确定使用的 pkg 和 pkg-fecth 的版本,目前最后一个 ...
- 使用天翼云云容器引擎CCE创建简单nginx服务
本文分享自天翼云开发者社区<使用天翼云云容器引擎CCE创建简单nginx服务>,作者:b****n 一.创建一个nginx应用. 1.选择资源池,如[杭州2],进入云容器引擎CCE平台页面 ...
- DeepSeek R1本地与线上满血版部署:超详细手把手指南
一.DeepSeek R1本地部署 1.下载ollama下载地址 本人是Mac电脑,所以选第一项,下面都是以Mac环境介绍部署,下载好把ollama运行起来即可启动Ollama服务. Ollama默认 ...
- 克鲁斯焊机GL 270引弧困难维修
克鲁斯焊机维修: 对于客户而言,其受益之处在于所有的机械手系统部件,从机械手控制.工件.定位器.传感器到电源和焊枪,都是由一家供应商开发和制造的.而诸如熔化极惰性气体/活性气体保护双丝焊接技术.等离子 ...
- Javascript 显示当前滚动条滚动的百分比
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 4个Sprint目标的挑战以及解决的技巧
1. Sprint 目标太大 有时,您的团队可能会尝试将过多的任务塞进冲刺中.抵制在冲刺中承担太多的诱惑,因为这会损害你的速度和持续交付的能力. 2. Sprint目标是模糊的 冲刺目标通常是不确定的 ...