自定义VektorInt类subvector方法异常:末尾为0/insert仅返回首元素
我正在学习类与对象的使用,编写了自定义VektorInt类,已经实现可用的add和insert方法。现在需要实现subvector方法,要求创建一个包含原向量索引a到b-1元素、容量与原向量一致的新向量对象。
目前遇到两个问题:
- 使用
add方法实现时,返回结果接近正确,但末尾元素被替换为0; - 使用
insert方法实现时,循环提前终止,仅返回第一个元素;最初尝试按数组方式复制插入也得到相同结果。
以下是VektorInt类定义及相关方法:
类定义
public class VektorInt{ private int[] elementi; private int stElementov; private static final int START_CAPACITY = 10; //konstanta, lahko jo večkrat uporabimo public VektorInt(int startCapacity){ this.elementi = new int[startCapacity]; this.stElementov = 0; } public VektorInt() { this(START_CAPACITY); } }
相关操作方法
public void set(int index, int value){ if(index > this.elementi.length){ throw new IndexOutOfBoundsException(); } this.elementi[index] = value; } public void add(int value){ this.expandIfNeeded(); this.elementi[this.stElementov] = value; this.stElementov++; } private void expandIfNeeded(){ if (this.stElementov >= this.elementi.length){ int[] stariElementi = this.elementi; this.elementi = new int[2*stariElementi.length]; for(int i = 0; i < this.stElementov; i++){ this.elementi[i] = stariElementi[i]; } } } public void insert(int index, int value){ this.expandIfNeeded(); for(int i = this.stElementov - 1; i >= index; i--){ this.elementi[i + 1] = this.elementi[i]; } this.elementi[index] = value; this.stElementov++; }
有问题的subvector方法
public VektorInt subvector(int start, int end){ VektorInt subvector = new VektorInt(this.elementi.length); for(int i = start; i <= (end) - 1; i++){ subvector.add(elementi[i]); } subvector.stElementov++; return subvector; }
调用System.out.println(vektor.subvector(0, 6))返回[2, 3, 4, 5, 6, 1, 0],想请教:替换为insert方法后为何仅返回首元素?初始化足够大的容量为何仍无效?
一、使用add时末尾出现0的原因
你当前的subvector方法中,循环结束后多执行了subvector.stElementov++;,这会让stElementov的数值比实际添加的元素数多1。打印向量时会遍历到这个超出实际元素的索引位置,而Java中int数组默认初始化值是0,所以末尾会出现0。
比如你从0到5(end=6,end-1=5)一共添加了6个元素,stElementov原本应为6,加1后变成7,打印时就会取到第7个位置的默认0值。
修复方法:直接删除subvector.stElementov++;这一行。
二、使用insert仅返回首元素的原因
核心问题出在两个地方:
set方法的索引判断错误:你的set方法判断条件是if(index > this.elementi.length),但数组的合法索引范围是0到elementi.length-1,当index等于elementi.length时,判断不会触发异常,但执行elementi[index] = value会直接抛出ArrayIndexOutOfBoundsException,导致循环终止,最终只插入了第一个元素。insert方法缺少索引合法性检查:如果插入的index超出0到stElementov的范围,会触发上述数组越界问题,或者导致元素插入位置错误。
另外,如果你在循环中错误地固定使用索引0插入元素,每次新元素都会放在最前面,最终结果会是倒序,但不会只返回首元素——这种情况大概率是越界异常导致循环提前中断。
三、初始化容量足够但无效的原因
向量的实际元素数量由stElementov控制,而非数组容量。哪怕初始化了足够大的容量,如果stElementov的数值不正确(比如之前多执行的++操作),打印时会遍历到数组中未赋值的位置,从而出现0或者元素数量错误的情况。
四、正确实现方案
修复后的subvector方法(使用add)
public VektorInt subvector(int start, int end){ // 先做参数合法性检查,避免索引越界 if(start < 0 || end > this.stElementov || start >= end){ throw new IllegalArgumentException("Invalid start or end index"); } VektorInt subvector = new VektorInt(this.elementi.length); for(int i = start; i < end; i++){ // 用i < end更直观,替代i <= end-1 subvector.add(this.elementi[i]); } return subvector; }
使用insert的正确实现
public VektorInt subvector(int start, int end){ if(start < 0 || end > this.stElementov || start >= end){ throw new IllegalArgumentException("Invalid start or end index"); } VektorInt subvector = new VektorInt(this.elementi.length); for(int i = start; i < end; i++){ // 插入到subvector的当前末尾,等价于add subvector.insert(subvector.stElementov, this.elementi[i]); } return subvector; }
同步修复set和insert的索引检查
// 修复set方法的索引判断 public void set(int index, int value){ if(index < 0 || index >= this.stElementov){ throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.stElementov); } this.elementi[index] = value; } // 给insert方法添加索引合法性检查 public void insert(int index, int value){ if(index < 0 || index > this.stElementov){ throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.stElementov); } this.expandIfNeeded(); for(int i = this.stElementov - 1; i >= index; i--){ this.elementi[i + 1] = this.elementi[i]; } this.elementi[index] = value; this.stElementov++; }
内容的提问来源于stack exchange,提问作者Kalina

