Подтвердить что ты не робот

Массив примитивного типа массива в массив объектов в java

Почему я не могу сделать это в java?

Object[] o = (Object[])(new int[]{0,1,2,3.14,4});

У меня есть метод, который получает объект, а затем представляет его как строку, но в зависимости от его типа (примитивная, примитивная оболочка, массив и т.д.). Когда я создавал Unit test, я передавал массив как Object, который работает нормально, но когда я выполняю трансляцию этого объекта в Object [], я получаю ClassCastException. Это происходит только с массивами примитивных типов. Есть ли способ избежать такого поведения? Если нет, может кто-нибудь объяснить, в чем причина такого поведения на виртуальной машине Java.

Любая помощь очень ценится.

4b9b3361

Ответ 1

Примитивный тип не может быть преобразован таким образом. В вашем случае существует массив двойных значений, что является причиной 3.14. Это будет работать:

    List<Object> objectList = new ArrayList<Object>();
    objectList.addAll(Arrays.asList(0,1,2,3.14,4));

Даже это работает:

List<Object> objectList = new ArrayList<Object>();
objectList.addAll(Arrays.asList(0,"sfsd",2,3.14,new Regexp("Test")));
for(Object object:objectList)
{
    System.out.println(object);
}

UPDATE Хорошо, там, как было сказано, нет прямого способа применить примитивный массив к объекту []. Если вам нужен метод, который преобразует любой массив в String, я могу предложить этот способ

public class CastArray {

    public static void main(String[] args) {
        CastArray test = new CastArray();
        test.TestObj(new int[]{1, 2, 4});
        test.TestObj(new char[]{'c', 'a', 'a'});
        test.TestObj(new String[]{"fdsa", "fdafds"});
    }

    public void TestObj(Object obj) {
        if (!(obj instanceof Object[])) {
            if (obj instanceof int[]) {
                for (int i : (int[]) obj) {
                    System.out.print(i + " ");
                }
                System.out.println("");
            }
            if (obj instanceof char[]) {
                for (char c : (char[]) obj) {
                    System.out.print(c + " ");
                }
                System.out.println("");
            }
            //and so on, for every primitive type.
        } else {
            System.out.println(Arrays.asList((Object[]) obj));
        }
    }
}

Да, это раздражает писать цикл для каждого примитивного типа, но нет другого пути, ИМХО.

Ответ 2

В Java примитивные типы и ссылочные типы представляют собой два разных мира. Это отражает массивы: примитивный массив не является массивом объектов, поэтому вы не можете использовать его.

Вот более простая версия вашего решения в вопросе:

private Object[] getArray(Object val){
    if (val instanceof Object[])
       return (Object[])val;
    int arrlength = Array.getLength(val);
    Object[] outputArray = new Object[arrlength];
    for(int i = 0; i < arrlength; ++i){
       outputArray[i] = Array.get(val, i);
    }
    return outputArray;
}

Это будет по-прежнему работать, когда они иногда решат добавить новые примитивные типы в виртуальную машину.

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

private Object[] getArray(Object val){
    int arrlength = Array.getLength(val);
    Object[] outputArray = new Object[arrlength];
    for(int i = 0; i < arrlength; ++i){
       outputArray[i] = Array.get(val, i);
    }
    return outputArray;
}

Конечно, это не кастинг, а преобразование.

Ответ 3

Вот простой однострочный слой:

Double[] objects = ArrayUtils.toObject(primitives);

Вам нужно будет импортировать Apache commons-lang3:

import org.apache.commons.lang3.ArrayUtils;

Ответ 4

Другая реализация функции getArray с гибкой обработкой примитивных типов:

public static Object[] createArrayFromArrayObject(Object o) throws XYZException {
    if(!o.getClass().isArray())
        throw new XYZException("parameter is not an array");

    if(!o.getClass().getComponentType().isPrimitive())
        return (Object[])o;

    int element_count = Array.getLength(o);
    Object elements[] = new Object[element_count];

    for(int i = 0; i < element_count; i++){
        elements[i] = Array.get(o, i);          
    }

    return elements;
}

Ответ 5

Первоначально опубликовано OP в самом вопросе, но вытащил его в качестве отдельного ответа.


После получения ответа от StKiller и других пользователей Мне удалось создать более общий метод, который находится ниже:

private final Class<?>[] ARRAY_PRIMITIVE_TYPES = { 
        int[].class, float[].class, double[].class, boolean[].class, 
        byte[].class, short[].class, long[].class, char[].class };

private Object[] getArray(Object val){
    Class<?> valKlass = val.getClass();
    Object[] outputArray = null;

    for(Class<?> arrKlass : ARRAY_PRIMITIVE_TYPES){
        if(valKlass.isAssignableFrom(arrKlass)){
            int arrlength = Array.getLength(val);
            outputArray = new Object[arrlength];
            for(int i = 0; i < arrlength; ++i){
                outputArray[i] = Array.get(val, i);
                            }
            break;
        }
    }
    if(outputArray == null) // not primitive type array
        outputArray = (Object[])val;

    return outputArray;
}

Вы можете передать вид массива в метод getArray, который вернет Object [], не бросая ClassCastException.

Еще раз спасибо за все ваши ответы.

Ответ 6

Примитивные типы не являются объектами. Нет обходного пути, вы можете использовать любые массивы, содержащие объекты Object [], но не массивы, содержащие примитивные типы.

Ответ 7

Вы можете сделать:

int[] intArray = new int[]{0,1,2,3,14,4};
ArrayList<MyObject> myObjArray = new ArrayList<MyObject>;

for (int i = 0; i < intArray.length; i++) {
myObjArray.set(new MyObject(intArray[i]));
}

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

Ответ 8

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

Object o = new String ("simple assignment");
String s = (String) o; 

Там, где нет трансформации объекта, он просто распаковывается как то, что он есть, каким он был всегда.

Integer [] ia = new Integer [] {4, 2, 6};
Object  [] oa = ia;     

Но примитивные ints не являются объектами, поэтому они не могут быть назначены массиву Object. Кастинг, однако, по возможности сыграл бы роль в противоположном направлении.

Ответ 9

Как только первоначальный плакат впервые заявил в своем вопросе:

У меня есть метод, который получает объект и затем представляет его как строку

В то время как цель состояла в том, чтобы показать значение Object дружественным образом, он использовал Casting как среднее значение для этой цели. Поэтому, расширяя на Paŭlo Ebermann ответ, вот мое решение, чтобы сделать большинство объектов toString() дружественными.

Основная проблема заключается в том, что массивы рекурсивно преобразуют любой массив X[] в его эквивалент объекта List<X>, является ли X примитивным или нет. Остальное обрабатывается каждым конкретным объектом toString(), если это необходимо, как и должно быть.

Важное предупреждение: предполагается, что нет круговых ссылок!

Учитывая

System.out.println(objectify(new double[][]{{65.5 * 15.9, 0}, {0.123456, 1}}))

Ожидаемый результат:

[[1041.45, 0.0], [0.123456, 1.0]]

Реализация:

public Object objectify(Object obj) {
    if(obj == null)
        return obj;
    Object o = obj;
    if(obj.getClass().isArray()) {
        // array
        if(obj instanceof Object[]) {
            // array of Object
            Object[] oI = (Object[])obj;
            Object[] oO = new Object[oI.length];
            for(int i = 0; i < oI.length; i++) {
                // objectify elements
                oO[i] = objectify(oI[i]);
            }
            o = Arrays.asList(oO);
        } else {
            // array of primitive
            int len = Array.getLength(obj);
            Object[] out = new Object[len];
            for(int i = 0; i < len; i++)
                out[i] = Array.get(obj, i);
            o = Arrays.asList(out);
        }
    }
    return o;
}

Ответ 10

С помощью Java 8 вы можете использовать Streams с функцией отображения, чтобы превратить массив в один из следующих типов:

Foo[] fooArray = ...;
Bar[] barArray = Arrays.stream(fooArray).map(object -> (Bar) object).toArray();

Предполагая, что данный объект можно присваивать типу, в который вы его вставляете. В вашем случае вы можете повернуть массив Integer в массив объектов несколько иначе, поскольку целочисленный поток имеет другой способ отображения объектов:

Arrays.stream(intArray).mapToObj(i -> (Object) i).toArray();