gpt4 book ai didi

java - 使用 [] 调用时出现奇怪的 java.lang.ClassCastException

转载 作者:塔克拉玛干 更新时间:2023-11-01 23:02:07 26 4
gpt4 key购买 nike

我正在为我的游戏使用 LibDGX 库。我遇到了常见的异常 ClassCastException , 但它发生在奇怪的情况下。

我正在使用 Animation来自 LibGDX 库的类。

只有当我使用 [] 时,我才会在这一行 收到错误消息操作。

val tex = animation.keyFrames[0]

如果我将其更改为 get() 错误消失

tex = animation.keyFrames.get(0)

这是完整的方法。我简化了示例。

override fun create() {


val frames = Array<TextureRegion>()
frames.add(TextureRegion(Texture("badlogic.jpg")))

val animation = Animation(frames)

val tex1 = animation.keyFrames.get(0) // Compiles

val tex = animation.keyFrames[0] // error - [Ljava.lang.Object; cannot be cast to [Lcom.badlogic.gdx.graphics.g2d.TextureRegion;


}

很奇怪,不是吗?

这是我用来最小化其他错误原因的动画类。它与 LibGDX api 中的相同。

    public class Animation<T> {

T[] keyFrames;
private float frameDuration;


public Animation (float frameDuration, Array<? extends T> keyFrames) {
this.frameDuration = frameDuration;

Class arrayType = keyFrames.items.getClass().getComponentType();
T[] frames = (T[]) ArrayReflection.newInstance(arrayType, keyFrames.size);
for (int i = 0, n = keyFrames.size; i < n; i++) {
frames[i] = keyFrames.get(i);
}

setKeyFrames(frames);
}

protected void setKeyFrames (T... keyFrames) {
this.keyFrames = keyFrames;
}
}

我还注意到如果我使用 Array.with 错误消失 build 而不是创造Array<TextureRegion>我的意思是 LibGDX Array不是来自 Kotlin。

val animation = Animation(Array.with(TextureRegion(Texture("badlogic.jpg"))))

您能告诉我发生这种情况的原因还是可能是错误?

最佳答案

编辑:在旧版本的 libGDX 中,Animation 不使用 Array 的反射功能。如果它,您就不会出现此错误,因为数组的类型是正确的!它应该在 1.9.7 版本的 libGDX 中。注意:创建时必须指定ArrayClass

这最近已在 #4476 中修复.但是,get[] 导致数组的不同字节码的以下“错误”可能仍然值得报告/询问。


这很有趣!

反编译

val tex1 = animation.keyFrames.get(0)

给予

ALOAD 2INVOKEVIRTUAL com/badlogic/gdx/graphics/g2d/Animation.getKeyFrames ()[Ljava/lang/Object;ICONST_0AALOADCHECKCAST com/badlogic/gdx/graphics/g2d/TextureRegionASTORE 3

while decompiling

val tex = animation.keyFrames[0]

给予

ALOAD 2INVOKEVIRTUAL com/badlogic/gdx/graphics/g2d/Animation.getKeyFrames ()[Ljava/lang/Object;CHECKCAST [Lcom/badlogic/gdx/graphics/g2d/TextureRegion;ICONST_0AALOADASTORE 4

It is important to note that the type of keyFrames is T[], so it cannot possibly have a custom get method (assuming no extensions exist.)

It seems that although the two should be equal ([] invokes operator fun get), they are not!

The only difference I can see is that the get variant checks the type (CHECKCAST) after retrieving it via AALOAD, while the [] variant attempts to check that the type of the array is T[] immediately after retrieving the array.

However, because frames is declared in Animation's constructor:

public Animation (float frameDuration, Array<? extends T> keyFrames) {
this.frameDuration = frameDuration;
T[] frames = (T[]) new Object[keyFrames.size];
for (int i = 0, n = keyFrames.size; i < n; i++) {
frames[i] = keyFrames.get(i);
}
setKeyFrames(frames);
}

作为

T[] frames = (T[]) new Object[keyFrames.size];

数组的实际类型是Object[]!因此,此转换为 TextureRegion[] 失败。

对我来说,这似乎是一个 libGDX 错误。


我可以很容易地用 Java 中的一个简单类重现它:

public class JavaObjWithArray<T> {

private T[] items;

public JavaObjWithArray(T[] items) {
this.items = (T[]) new Object[items.length];
System.arraycopy(items, 0, this.items, 0, items.length);
}

public T[] getItems() {
return items;
}

}

fun main(args: Array<String>) {
val obj = JavaObjWithArray(arrayOf("a", "b"))

val one = obj.items.get(0)
val two = obj.items[0]
}

这也会在 [] 的行上抛出一个 ClassCastException!此外,字节码也有相同的区别。


真正出现问题的是 Java(和 Kotlin)中缺少泛型数组。在 Java 中有两种主要的解决方案:

  • 存储一个 Object[] 并将值转换为 get
  • 存储一个 Object[],但将其转换为 T[]

这是个问题 - 因为数组的实际类型 Object[]。因此,这些“通用”数组不应该暴露!我能理解为什么 libGDX 这样做,即提高性能并消除方法调用的小开销,但这绝对是不安全的。


不过,get[] 不同的事实可能是一个错误。也许对此进行调查或提交错误报告可能会有所帮助。


Java bytecode instruction list

关于java - 使用 [] 调用时出现奇怪的 java.lang.ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47579524/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com