这种方法一直困扰着我好几个小时。它应该采用任何数据类型的类型X array
的一部分。这是我第一次使用泛型array
和调试器。
我从测试中得到的错误是:
expected: 'hello' but was 'null' and
0: ...ArrayOutOfBoundsException: 0
看起来ArrayOutOfBoundsException
处理也没有被正确抛出。
我不知道该怎么做。我的删除功能似乎工作正常。
public void insert( int index, X item )
{
if ( index > 0 || index < length )
{
length++;
X[] obj2 = (X[]) new Object[obj.length - 1];
for ( int i = 0; i == index; i++ )
{
obj2[i] = obj[i];
}
obj2[index] = item;
for ( int i = index; i == length; i++ )
{
obj2[i + 1] = obj[i];
}
obj = obj2;
}
else
{
throw new java.lang.ArrayIndexOutOfBoundsException("" + index);
}
}
@Test
public void testInsert()
{
XArray<String> b = new XArray<String>();
b.add("hello");
b.add("bye");
b.insert(1, "adios");
assertEquals("hello", b.get(0));
assertEquals("adios", b.get(1));
assertEquals("bye", b.get(2));
assertEquals(3, b.size());
b.insert(1, "buenos dias");
assertEquals(4, b.size());
assertEquals("hello", b.get(0));
assertEquals("buenos dias", b.get(1));
assertEquals("adios", b.get(2));
b.insert(0, "hi");
assertEquals(5, b.size());
assertEquals("hi", b.get(0));
assertEquals("hello", b.get(1));
b.insert(4, "see ya");
assertEquals(6, b.size());
assertEquals("see ya", b.get(4));
assertEquals("bye", b.get(5));
}
答案 0 :(得分:3)
你有一些问题。
1)假设length
是一个实例变量,它反映了length
数组的obj
,那么你实际上想要进行以下测试:
if (index >= 0 && index <= length)
这将测试您的 new 项索引是否为0或更多,或者比当前obj
数组中的最大索引大1(即等于当前数组长度)。 这在很大程度上取决于您的预期合同我认为您可以&#34;插入&#34;在列表的末尾,但您可能必须将其限制为仅插入中间,因此仅当存在另一个元素时。在这种情况下,你想要
if (length > 0 && index >= 0 && index < length)
注意:您需要测试&&
,而不是||
,因为您需要满足所有条件。如果你想在开头做一个更标准的参数有效性检查,你可以这样做:
if (index < 0 || index > length)
throw new java.lang.ArrayIndexOutOfBoundsException("" + index);
这样做的好处是无需else
块,并且可以略微减少代码嵌套。
2)然后你增加this.length
,然后你做new Object[obj.length - 1];
,这没有任何意义。我怀疑你想做:
length++;
@SuppressWarnings("unchecked")
X[] obj2 = (X[]) new Object[this.length];
或更好:
@SuppressWarnings("unchecked")
X[] obj2 = (X[]) new Object[++length];
3)你的第一个循环for ( int i = 0; i == index; i++ )
,它应该是:
for (int i = 0; i < index; i++)
这是因为循环条件语句不会测试突破条件(即当这是真的时停止)但是对于延续条件(即在i
小于index
时继续) )
4)你的第二个循环是for ( int i = index; i == length; i++ )
,应该这样做:
for (int i = index; i < length - 1; i++)
这是因为你的长度有所增加,但你使用i
来引用原始数组索引,而不是更大的数组索引。
总而言之,我认为它看起来像下面的代码。
这里最大的问题可能就是你的测试方法。你在一个大型测试中有几个测试。这并不能帮助你隔离个别错误,并在不破坏调试器的情况下解决你的方法有什么问题(双关语无意,但我只是看到了它,所以我将离开它)。理想情况下,如果您的单元测试很小,集中和隔离,则不应该使用调试器。最后包括这些测试的例子。
class XArray<X> {
private int length;
private X[] obj;
public XArray() {
this.obj = initBackingArray(0);
this.length = 0;
}
private X[] initBackingArray(int length) {
@SuppressWarnings("unchecked")
X[] result = (X[])new Object[length];
return result;
}
public X get(int index) {
return this.obj[index];
}
public int size() {
return this.length;
}
public void add(X item) {
insert(length, item);
}
public void insert( int index, X item )
{
if (index >= 0 && index <= length)
{
@SuppressWarnings("unchecked")
X[] obj2 = (X[]) new Object[++length];
for (int i = 0; i < index; i++)
{
obj2[i] = obj[i];
}
obj2[index] = item;
for (int i = index; i < length - 1; i++)
{
obj2[i+1] = obj[i];
}
obj = obj2;
}
else
{
throw new java.lang.ArrayIndexOutOfBoundsException("" + index);
}
}
}
示例测试:
@Test
public void testAddOnceWorks() {
XArray<String> b = new XArray<String>();
b.add("hello");
}
@Test
public void testAddTwiceWorks() {
XArray<String> b = new XArray<String>();
b.add("hello");
b.add("bye");
}
@Test
public void testInsertOnEmptyWorks() {
XArray<String> b = new XArray<String>();
b.insert(0, "hello");
}
@Test
public void testAddOnceInsertBeforeWorks() {
XArray<String> b = new XArray<String>();
b.add("hello");
b.insert(0, "hello");
}
答案 1 :(得分:1)
首先,您的边界检查逻辑不正确。 index
可能的每个值都大于0
或小于length
。这会导致您尝试创建的ArrayIndexOutOfBoundsException
不被抛出。 (如果你的数组超出界限,它可能会抛出自己的AIOOBE。)
您应该确保满足这两个条件。使用&&
代替||
。
if ( index > 0 && index < length )
此外,在将旧元素复制到新数组时,您需要意识到for
循环条件为true
意味着&#34;继续前进&#34;而不是&#34;停止& #34 ;.在index
尚未达到length
时继续循环播放。将==
更改为<
。
for ( int i = 0; i < index; i++ )
(另一个for
循环需要进行类似的更改。)