在java中将原始类型数组转换为对象数组

发布于 2024-10-31 18:10:38 字数 370 浏览 2 评论 0原文

为什么我不能在java中做到这一点?

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

我有一个方法,它接收一个对象,然后将其表示为字符串,但这取决于他的类型(原始、原始包装器、数组等)。当我创建单元测试时,我将一个数组作为 Object 传递,这是好的,但是当我将该对象强制转换为 Object[] 时,我得到 <强>ClassCastException。 这种情况仅发生在原始类型数组中。有什么办法可以避免这种行为吗?如果没有,有人可以解释一下 Java 虚拟机上这种行为的原因是什么。

非常感谢任何帮助。

Why I cannot do this in java?

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

I have a method that receives an object and then represents it as a string, but depending on his type (primitive, primitive wrapper, array, etc...). When I was creating a Unit test, I was passing an array as Object which is Ok, but when I perform cast of that object into Object[] I'm getting ClassCastException.
This is only happening with primitive type arrays. Is there any way to avoid this behavior? If not, could someone explain what is the reason of this behavior on Java Virtual Machine.

Any help is very appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

白芷 2024-11-07 18:10:38

这是一个简单的单行:

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

您需要导入 Apache commons-lang3

import org.apache.commons.lang3.ArrayUtils;

Here is a simple one-liner:

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

You will need to import Apache commons-lang3:

import org.apache.commons.lang3.ArrayUtils;
穿越时光隧道 2024-11-07 18:10:38

在 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;
}

当然,这不是强制转换,而是转换

In Java, primitive types and reference types are two distinct worlds. This reflects to arrays: A primitive array is not an object array, that's why you can't cast.

Here is a simpler version of your solution in the question:

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;
}

This will still work when they sometimes decide to add new primitive types to the VM.

Of course, you might want to do the copying always, not only in the primitive case, then it gets even simpler:

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;
}

Of course, this is not casting, but converting.

我要还你自由 2024-11-07 18:10:38

最初由 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。

再次感谢您的所有回复。

Originally posted by the OP within the question itself, but pulled here as a separate answer.


After getting response from StKiller and other users
I was able to create a more generic method, which is located below:

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;
}

You can pass kind of array into getArray method, which will return Object[] without throwing ClassCastException.

Thanks again for all your replies.

我们只是彼此的过ke 2024-11-07 18:10:38

原始类型不能以这种方式进行转换。
在你的例子中,有一个双精度值数组,原因是 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);
}

更新
好的,正如前面所说,没有直接的方法将原始数组转换为 Object[]。
如果你想要一个转换字符串中任何数组的方法,我可以建议这种方式

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));
        }
    }
}

是的,为每个基本类型编写一个循环很烦人,但没有其他方法,恕我直言。

Primitive type cannot be transformed in this way.
In your case, there is an array of double values, cause of 3.14.
This will work:

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

Even this works :

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
Ok, there as there was said, there is not direct way to cast a primitive array to an Object[].
If you want a method that transforms any array in String, I can suggest this way

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));
        }
    }
}

Yes, it's annoying to write a loop for every primitive type, but there is no other way, IMHO.

执笏见 2024-11-07 18:10:38

正如原发帖者首先在他的问题中所说:

我有一个接收对象然后将其表示为字符串的方法

虽然目的是以友好的方式输出对象的值,但他使用强制转换作为意思 为此。因此,扩展 Paŭlo Ebermann 的答案,这是我的解决方案,使大多数对象 toString() 友好。

主要问题是数组,它会递归地将任何数组 X[] 转换为其相当于 List 的对象,无论 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;
}

As the original poster first stated in his question:

I have a method that receives an object and then represents it as a string

While the intent was to output an Object's value in a friendly way, he was using Casting as a mean to that end. Therefore, expanding upon Paŭlo Ebermann's answer, here is my solution to make most objects toString() friendly.

The main problem being arrays, it will recursively transform any array X[] into its Object equivalent of List<X>, whether X is a primitive or not. The rest is be handled by each specific object's toString() if needed, as it should.

Important caveat: it is assumed that there are no circular references!

Given:

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

The expected result is:

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

The implementation:

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;
}
被翻牌 2024-11-07 18:10:38

在 Java 8 中,您可以使用带有映射函数的 Streams 将数组转换为任何其他类型之一,如下所示:

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

假设给定的对象可分配给您将其转换为的类型。在您的情况下,您可以将整数数组转换为稍微不同的对象数组,因为整数流具有不同的映射对象的方式:

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

With Java 8 you could use Streams with a mapping function to turn the array into one of any other type like this:

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

Assuming that the given object is assignable to the type you are casting it into. In your case you could turn an Integer array into an object array slightly differently as an integer stream has a different way of mapping objects:

Arrays.stream(intArray).mapToObj(i -> (Object) i).toArray();
影子的影子 2024-11-07 18:10:38

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;
}

Another implementation for the getArray function with flexible handling of primitive types :

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;
}
各空 2024-11-07 18:10:38

您可以这样做:

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 类中)。

You could do:

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]));
}

You'd need to define a class where the constructor sets the integer parameter to an instance field (in the MyObject class).

薄情伤 2024-11-07 18:10:38

您只能转换派生类型的对象,该对象作为基类型处理和传递。在相反的方向上,您可以将派生类型分配给基类型:

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

对象不会发生任何转换 - 它只是被揭开它本来的样子,它一直是什么。

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

原始整数不是对象,因此它们不能分配给对象数组。然而,如果可能的话,选角只会在相反的方向上发挥作用。

You can only cast an object of type derived type, which is handled and passed as base type. In the opposite direction, you can just assign a derived type to a base type:

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

There in no transformation of the Object going on - it is just demasked as what it is, what it always was.

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

But primitive ints aren't Objects, hence they can't be assigned to an Object array. Casting, however, would, if possible, only play a role in the opposite direction.

简美 2024-11-07 18:10:38

这里给出的答案都不适用于多维数组,所以这是我的通用包装器。它适用于任何类型和任何维度的数组,并且还可以正确处理空引用(包括深度隐藏的引用)。

import java.lang.reflect.Array;
import java.util.Arrays;

public class ArrayWrapper {
    private static Object[] deepWrap(Class<?> componentClass, Object a) {
        if (a == null)
            return null;
        Object[] result = (Object[])Array.newInstance(componentClass, Array.getLength(a));
        if (componentClass.isArray()) {
            Class<?> innerCompClass = componentClass.getComponentType();
            Object[] b = (Object[])a;
            Arrays.parallelSetAll(result, i -> deepWrap(innerCompClass, b[i]));
        } else
            Arrays.setAll(result, i -> Array.get(a, i));
        return result;
    }

    public static Object[] wrap(Object a) {
        if (a == null)
            return null;
        Class<?> c = a.getClass();
        if (!c.isArray())
            throw new IllegalArgumentException("Not an array");
        int dimension = 0;
        do {
            dimension++;
            c = c.getComponentType();
        } while (c.isArray());
        if (!c.isPrimitive())
            return (Object[])a;
        c = Array.get(Array.newInstance(c, 1), 0).getClass();
        while (--dimension > 0)
            c = Array.newInstance(c, 0).getClass();
        return deepWrap(c, a);
    }
}

使用演示:

public static void main(String[] args) {
    final int size1 = 5;
    final int size2 = 4;
    int[][] b = new int[size1][size2];
    for (int i = 0; i < size1; i++)
        for (int j = 0; j < size2; j++)
            b[i][j] = (i + 1) * (j + 1);
    b[1] = new int[7];
    b[1][4] = 4;
    b[3] = null;
    System.out.println(b.getClass().getCanonicalName());
    System.out.println(Arrays.deepToString(b));
    Integer[][] w = (Integer[][])wrap(b);
    System.out.println(w.getClass().getCanonicalName());
    System.out.println(Arrays.deepToString(w));
}

None of the answers presented here work with multidimensional arrays, so here's my universal wrapper. It works with arrays of any type and any dimension, and also correctly handles null references (including deeply hidden ones).

import java.lang.reflect.Array;
import java.util.Arrays;

public class ArrayWrapper {
    private static Object[] deepWrap(Class<?> componentClass, Object a) {
        if (a == null)
            return null;
        Object[] result = (Object[])Array.newInstance(componentClass, Array.getLength(a));
        if (componentClass.isArray()) {
            Class<?> innerCompClass = componentClass.getComponentType();
            Object[] b = (Object[])a;
            Arrays.parallelSetAll(result, i -> deepWrap(innerCompClass, b[i]));
        } else
            Arrays.setAll(result, i -> Array.get(a, i));
        return result;
    }

    public static Object[] wrap(Object a) {
        if (a == null)
            return null;
        Class<?> c = a.getClass();
        if (!c.isArray())
            throw new IllegalArgumentException("Not an array");
        int dimension = 0;
        do {
            dimension++;
            c = c.getComponentType();
        } while (c.isArray());
        if (!c.isPrimitive())
            return (Object[])a;
        c = Array.get(Array.newInstance(c, 1), 0).getClass();
        while (--dimension > 0)
            c = Array.newInstance(c, 0).getClass();
        return deepWrap(c, a);
    }
}

Usage demo:

public static void main(String[] args) {
    final int size1 = 5;
    final int size2 = 4;
    int[][] b = new int[size1][size2];
    for (int i = 0; i < size1; i++)
        for (int j = 0; j < size2; j++)
            b[i][j] = (i + 1) * (j + 1);
    b[1] = new int[7];
    b[1][4] = 4;
    b[3] = null;
    System.out.println(b.getClass().getCanonicalName());
    System.out.println(Arrays.deepToString(b));
    Integer[][] w = (Integer[][])wrap(b);
    System.out.println(w.getClass().getCanonicalName());
    System.out.println(Arrays.deepToString(w));
}
浅浅淡淡 2024-11-07 18:10:38

原始类型不是对象。没有解决方法,您可以将任何包含对象的数组强制转换为 Object[],但不能将包含基本类型的数组强制转换。

Primitive types are not Objects. There is no workaround, you can cast any arrays that contain objects to Object[], but not arrays that contain primitive types.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文