2015-04-15 3 views
2

У меня возникла проблема с компиляцией моего проекта java, потому что целое число длины массива (которое является переменной) не подменяет корректно в моем массиве объектов.Длина массива Java Variable

import java.util.Arrays; 

public class ObjectList { 
    private int N; 
    private Object[] fractionList = new Object[N]; 

    public ObjectList(int n){ 
     this.N = n; 
    } 

    public int capacity(){ 
     return this.N; 
    } 

    public void setN(int n){ 
    this.N = n; 
    } 

    public String toString(){ 
     return Arrays.toString(fractionList); 
    } 
} 

public class FractionDriver { 
    public static void main(String[] args){ 

    // creates the object list, sets N to 4 
    ObjectList list = new ObjectList(4); 

    System.out.println("The Objectlist has " + list.capacity() + " lines"); 

    // prints the array 
    System.out.println(list.toString()); 
    } 
} 

это то, что компилятор выводит:

The ObjectList has 4 lines 
[] 

Из-за этого я не могу добавить любые объекты в моем массиве. Компилятор бросает ArrayIndexOutOfBoundsException: 0 и сообщает мне, что в массиве нет элементов.

Если я выбираю заменить N в переменной экземпляра массива объектов, например, так:

private Object[] fractionList = new Object[4]; 

Компилятор счастлив и устанавливает длину массива до 4.

Что я делаю не так?

+1

сообщение не получено из компилятора. это выход вашей программы. – Joshua

+0

Не забывайте отмечать ответ как принятый или запрашивать разъяснения в комментариях к ответу, если вы все еще нуждаетесь в помощи, @nisoramen. –

ответ

4

Вы можете создать экземпляр массива в конструкторе, где длина уже известна:

private Object[] fractionList; 

public ObjectList(int n){ 
    this.N = n; 
    this.fractionList = new Object[n]; 
} 

Однако, вы также можете воссоздать массив, когда вы измените значение N:

public void setN(int n){ 
    this.N = n; 
    // consider copying data from the old array to the new array 
    this.fractionList = new Object[n]; 
} 
+1

В методе setN мы должны не только воссоздать, но и обрабатывать клонирование существующих элементов в новый массив, но это лишь небольшое улучшение :) – Beri

+0

@Beri да, я упомянул об этом в комментарии внутри кода. Однако это зависит от требуемой логики setN. Конечно, вы также должны обрабатывать случай, когда новый массив слишком мал, чтобы соответствовать элементам старого массива. – Eran

2

проблема заключается в том, что линия

private Object[] fractionList = new Object[N]; 

выполняется перед конструктором. Порядок инициализации всегда выглядит следующим образом:

  1. Если суперкласс - инициализировать его первый
  2. статическая переменная декларирование и статические инициализаторы в порядке появления
  3. экземпляра декларации переменной и экземпляра инициализаторах в порядке появления
  4. Конструктор.

Вы хотите, чтобы код в вашем конструкторе (4) задавал длину массива, но массив уже был создан в вашей переменной экземпляра (3).

я рекомендую следующее:

public class ObjectList { 
    private int N; 
    private Object[] fractionList; 

    public ObjectList(int n){ 
     fractionList = new Object[n]; 
     this.N = n; 
    } 

    public int capacity(){ 
     return this.N; 
    } 

    public void setN(int n){ 
     // might want to copy content from old array to new one here 
     fractionList = new Object[n]; 
     this.N = n; 
    } 

    public String toString(){ 
     return Arrays.toString(fractionList); 
    } 
} 

Если вы хотите, чтобы соответствовать Java Beans, я также рекомендую переименовать метод capacity() в getCapacity().

1

Во-первых, это не ошибка компиляции. Программа компилируется в порядке. Проблема в том, что массив fractionList инициализируется до. Тело конструктора вызывается, где задана переменная N.

Вы можете переместить инициализации в конструкторе:

private Object[] fractionList; 


public ObjectList(int n) { 
    this.N = n; 
    fractionList = new Object[N]; 
} 
0

хорошо ...в простом слове, когда инициализируется Object[] fractionList, значение поля N является «невидимым», поскольку его значение не будет установлено до тех пор, пока не будет вызвано значение this.N = n;, в отличие от буквального числа 4, которое является константой времени компиляции.

Вы можете передать параметру N конструктору для инициализации массива. Что-то вроде:

public ObjectList(int n){ 
    this.fractionList = new Object[n]; 
} 
Смежные вопросы