我有这个方法:
//not related to the error, but included for reference
ArrayList<ArrayList<Color>> a = new ArrayList<ArrayList<Color>>();
void addColorToList(float[] j) //this array always length 3
{
float[] k = Arrays.copyOf(j, 3);
Arrays.sort(k);
//Error in the following line
a.get(Arrays.asList(j).indexOf(k[0])).add(new Color(j[0], j[1], j[2]));
}
并出现此错误:
Exception in thread "AWT-EventQueue-1"
java.lang.ArrayIndexOutOfBoundsException: -1
我已确定我的代码始终使用-1调用a.get()
,因为Arrays.asList(j). indexOf(k[0])
找不到该元素。但是,我无法弄清楚为什么这不能像我期望的那样工作。我尝试打印出Arrays.asList(j)
的结果,但我不确定结果如何:[[F@307af497]
。谁能告诉我这是什么问题?
答案 0 :(得分:3)
让我们从这开始:
我尝试打印出Arrays.asList(j)的结果,但我不确定结果如何:[[F @ 307af497]。
您正在使用(有效)toString()
方法打印列表。所以...
外部'['和']'来自列表格式。
您有一个由一个元素组成的列表。
该元素是float
的数组。 ([F@307af497
由Object.toString()
生成,[F
是float[]
类型的呈现方式......)
这实际上是一个重要的线索。 Arrays.asList(float [])返回一个“float []”列表......
但为什么?
嗯,因为这就是应该做的!!
Arrays.asList
签名为Arrays.asList<T>(T ...)
。这意味着它需要一个显式的T[]
...或一个零个或多个T
个实例的序列,然后将它包装为Object[]
。然后将Object[]
打包为List<Object>
(粗略地说)。
这里的关键是实际类型T 必须是引用类型...而不是基本类型。
但是您的代码似乎期待像Arrays.asList(float ...)
这样的重载方法...并期望这会让您的float[]
包裹为List<Float>
。
不幸的是,asList
没有这样的重载。
所以实际发生的是:
您的通话绑定到Arrays.asList<float[]>(float[] ...)
varargs导致j
被包裹在一个数组中;即相当于new float[][]{j}
结果是List<float[]>
...的一个实例,包含一个元素。
那么解决方案是什么?
一般......
一种解决方案是将您的花车代表Float[]
而不是float[]
。理想情况下,您可以将此更改推回到首先创建数组的代码,等等。
第二种解决方案是在调用float[]
之前将Float[]
转换为asList
。这样做的简单方法是使用简单的循环。 (可能还有第三方库用于执行此操作。)缺点是:
每次调用此方法时都需要进行转换,如果你多次调用它可能会很昂贵,并且
原始数组与已包装的数组之间没有连接...如果您想通过列表包装器更新数组。
但在这种情况下,最佳解决方案就是简单地替换它:
Arrays.asList(j).indexOf(k[0])
使用一个简单的循环迭代原始float[]
测试,找到与k[0]
匹配的条目。
这个故事的寓意:你可以通过努力寻找一个优雅的Java解决方案轻松拍摄自己。
通常,愚蠢的代码更好。 (两者都更快,更正确。)