我试图创建一个同时尽可能节省空间的对象,但也可以一般地工作,并且我遇到了一个重大问题。我想做的一个优化是从键中删除包装器(其中可以有任意数量的任意类型)。但我遇到了Java中泛型的本质问题。
似乎要使函数通用,它必须接受需要包装类的对象。如果我可以动态创建基本类型数组,那么解决方法就是。有谁知道我怎么能做到这一点?
答案 0 :(得分:2)
首先,我怀疑你的意图会在存储方面做出任何可衡量的改进,但要回答这个问题......
我假设您的问题可以概括为"如果传递了包装器对象,我如何将它们存储为基元数组?",并暗示不允许null
个对象。 / p>
您可以使用JDK中的库方法动态创建基本数组。您还没有显示任何代码,因此请根据需要进行修改:
这是一个简单的方法:
public static int[] unwrap(Integer... integers) {
int[] array = new int[integers.length];
for (int i = 0; i < integers.length; i++) {
array[i] = integers[i]; // auto-unboxing
}
return array;
}
您可能只是为不同的包装器类型重载构造函数或工厂方法。
这是一个如何动态创建基本数组的更一般的例子:
public static int[] unwrap(Integer... integers) {
int[] array = (int[]) Array.newInstance(int.class, integers.length);
for (int i = 0; i < integers.length; i++) {
array[i] = integers[i].intValue();
}
return array;
}
你可以为你的其他包装器类调整这个模式,例如通过存储在一个包装类使用哪个原始类(例如Integer.class --> int.class
这里)的地图中,但是当涉及到正确的时候问题变得更加棘手来自包装器的值,例如,知道为Integer.intValue()
调用int
,为Long.longValue()
调用long
。
但是,你可以反思性地解决这个问题:
private static Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>() {{
put(Integer.class, int.class);
put(Long.class, long.class);
put(Float.class, float.class);
put(Double.class, double.class);
put(Character.class, char.class);
put(Short.class, short.class);
put(Byte.class, byte.class);
put(Boolean.class, boolean.class);
}};
public static <T> Object unwrap(T first, T... rest) throws Exception {
Class<?> outputType = map.get(first.getClass());
if (outputType == null) {
throw new UnsupportedOperationException();
}
Object array = Array.newInstance(outputType, rest.length + 1);
Method getter = first.getClass().getMethod(outputType.getSimpleName() + "Value");
for (int i = 0; i < rest.length + 1; i++) {
T target = i == 0 ? first : rest[i - 1];
Array.set(array, i, getter.invoke(target));
}
return array;
}
剩下的问题是原始数组不是Object[]
的实例,所以你不能将返回类型声明为数组(没有常见的类型)对于原始数组)。
尽管如此,你可以保存你的数组对象,然后使用类似的方法进行查询,然后再调用包装器,除非你调用包装类的构造函数并从数组中传递一个元素,通过{{1 }}