не удалось преобразовать массив объектов в массив другого типа

#java

#java

Вопрос:

я дергал себя за волосы по ночам, когда получал ClassCastException при попытке преобразовать тип объекта в другой тип объекта…. Я настолько уверен, что этот код будет работать, потому что все объекты являются подклассами класса Object… но каким-то образом я получаю это исключение … кто-нибудь может помочь, ребята?

Извините, ребята .. не путать с оригинальным ArrayList, я изучаю программирование на Java и практикую приведение массивов объектов… исключение находится в строке 8, где я привел массив объектов к типу массива оружия … извините за любую форму троллинга…

 public class ArrayList {
    public static void main(String args[]){
        ArrayList arrayList = new ArrayList();
        weapon[] weapons = new weapon[5];
        for (int i = 0; i < weapons.length; i  ) {
            weapons[i] = new weapon(i);
        }
        weapons = (weapon[]) arrayList.add(weapons, 
                new weapon(weapons.length   1, "mp5"));
    }

    public Object[] add(Object[] targetObjectList, Object add){
        Object[] oldList = new Object[targetObjectList.length];
        for (int i = 0 ; i < oldList.length; i  ){
            oldList[i] = targetObjectList[i];
        }
        Object[] newList = new Object[oldList.length 1];

        for (int i = 0; i < oldList.length; i  ) {
            newList[i] = oldList[i];
        }
        newList[newList.length - 1] = add;
        return newList;
    }

}//end arrayList class

class weapon {
    String name;
    int id;
    public weapon(int id) {
        this.id = id;
        name = "weapon";
    }

    public weapon(int id, String name) {
        this.id = id;
        this.name = name;
    }
}
  

Комментарии:

1. Ваш код сбил меня с толку оригинальным классом ArrayList в java, я бы счел это действительно плохим стилем именования. P.S. даже методы (.add).

2. Я всего несколько дней на StackOverflow, и кажется, что здесь много троллей.

3. Вы затрудняете ответ на свой вопрос, не сообщая нам, откуда вы получаете исключение, и не публикуя трассировку стека.

4. Что вы пытаетесь сделать с этим кодом. Вы создали массив из 5 видов оружия. После этого вы просто пытаетесь создать 6-е оружие и поместить его в свой массив. Вы могли бы использовать java.util. ArrayList<weaopn> чтобы выполнить это и избавиться от вашего метода add. Вы также могли бы сохранить статический NextID в вашем классе weapon, чтобы он мог генерировать свой собственный идентификатор. Но вы, возможно, захотите объяснить, что вы пытаетесь сделать. В противном случае вы получите очень сложные и слегка неуместные ответы. (не то, чтобы контравариантность была плохой концепцией ..)

5. @Op De Cirkel — вы слышали о Hanlon’s Razor? Смотрите en.wikipedia.org/wiki/Hanlon’s_razor . Хотя, чтобы быть справедливым к OP и другим, подобным ему, проблема обычно не в глупости … но неспособность писать четко и / или непонимание предмета. Если вам трудно с этим справиться, вы, вероятно, зашли не на тот веб-сайт!

Ответ №1:

A weapon является Object ; следовательно, мы можем рассматривать массив af weapon как массив Object . Однако не все Object s являются weapon s; следовательно, массив Object не может обрабатываться как массив weapon Object — если только то, что кажется массивом weapon , на самом деле не было массивом из, чтобы начать с. Из-за этого ваш подход станет затруднительным. Вы могли бы попробовать

 weapon[] newList = new weapon[oldList.length 1];
  

вместо этого, но тогда вам нужно было бы изменить все массивы, чтобы они имели тип weapon[] , и метод не стал бы общим (что, я полагаю, и является вашей целью). Однако, если вам нужен метод, который может добавлять элемент в любой тип массива, вам следует вместо этого использовать generics.

P.S. Если вы изучаете программирование и массивы, написание такого add() метода является хорошим упражнением, но если вы «просто хотите, чтобы это работало», вам следует использовать ArrayList вместо этого, который выполняет всю работу по добавлению за вас.

Комментарии:

1. hmm…my цель состоит в том, чтобы изменить возвращаемый массив объектов на тип оружия array..is возможно ли это сделать без использования ArrayList?

2. @Shizumaru18: Нет, если вы начинаете с new Object[oldList.length 1] , потому что тогда вы получаете массив, который знает, что это Object массив. Вы можете поместить в него столько weapon символов, сколько захотите, но это все равно будет Object массив. Поскольку это Object массив, он фактически позволил бы вам поместить в него что угодно, скажем, Car или an Apple , и, следовательно, Java не позволит вам обрабатывать его как weapon массив. Моим советом было бы отказаться от использования Object and Object[] в add() и вместо этого использовать weapon and weapon[] .

Ответ №2:

Массивы являются подклассом Object . Вы не можете привести Object[] к weapon[] . Вот общее решение вашей проблемы:

 weapons = (weapon[])arrayList.add(weapons, new weapon(weapons.length   1, "mp5"),weapon.class);
  

и

 public <T> T[] add(T[] targetObjectList, T add, Class<T> c) {
    T[] oldList = (T[])Array.newInstance(c, targetObjectList.length);
    for (int i = 0; i < oldList.length; i  ) {
        oldList[i] = targetObjectList[i];
    }
    T[] newList = (T[])Array.newInstance(c, oldList.length   1);

    for (int i = 0; i < oldList.length; i  ) {
        newList[i] = oldList[i];
    }

    newList[newList.length - 1] = add;

    return newList;

}
  

Примечание: Следуйте Java Naming Conventions . Избегайте Java API имен классов в качестве имени вашего класса.

Комментарии:

1. Также System.arraycopy() — ваш друг; приведите к T[].

2. @karamkaze: да. но я только что исправил проблему с приведением.

Ответ №3:

  • Object o = new Foo() . Это нормально. Foo — это Object. Поскольку Foo extends Object
  • Foo f = new Object() Не в порядке, объект НЕ Foo (ошибка компилятора)
  • Foo f = (Foo)(new Object()) - ClassCastException

Ответ №4:

То, что вы хотите сделать, известно как контравариантность. Проблема, присущая вашему коду, заключается в том, что МАССИВ, который вы создаете в функции add, представляет собой массив объектов (независимо от того, чем эти объекты в конечном итоге являются).

Если бы вы сделали следующее, ваш код работал бы. Я думаю, что вам нужно работать с обобщениями в этом смысле (посмотрите на фактический класс ArrayList, поскольку он уже реализует это).

 ...snip...
    Object[] newList = new weapon[oldList.length 1];

    for (int i = 0; i < oldList.length; i  ) {
        newList[i] = oldList[i];
    }
    newList[newList.length - 1] = add;
    return newList;
...snip...
  

Вот пример кода, который работает так, как вы ожидаете.

 public class Test {

    public static void main(String[] args) {
        Integer[] i = (Integer[])Test.get();

    }

    public static Object[] get() {
        Object[] o = new Object[20];
        for(int i = 0; i < o.length; i  ) {
            o[i] = new Integer(0);
        }
        return o;
        }
}
  

У ArrayList есть метод .toArray(T[] a), который вернет увеличенный размер массива, содержащий ваши новые элементы. Итак, как работает эта контравариантность? Через пакет java.reflect. Это очень маленький отрывок о том, как это на самом деле работает (есть несколько разных пакетов, которые работают вместе, чтобы приступить к этому.)

 ...Object[] function(Object[] typearray) {
    Object[] o = (Object[]) Array.newInstance(typearray.getClass().getComponentType(), 20);
    ...fill...
    return o;
}
  

Причина, по которой вы должны это сделать, заключается в том, что МАССИВ (поскольку все в Java является объектами) сам является объектом, тогда массив объектов не может быть преобразован в массив целых чисел. Если вы преобразовали массив целых чисел из массива в массив объектов (как показано в приведенном выше примере), а затем снова преобразовали массив объектов в массив целых чисел (поскольку мы никогда не отбрасывали базовый класс, являющийся массивом целых чисел).