美好的一天,
我尝试了很好的谷歌搜索,甚至一些阅读,但不确定如何继续。这是问题所在:
当我在java.nio.Buffer的任何实现上调用duplicate()
时,不保留我用原始缓冲区buf.order(ByteOrder.LITTLE_ENDIAN)
设置的字节顺序。这是个问题。所以我开始创建一个静态方法,允许我像这个例子一样执行以下操作:
public static ByteBuffer endianPreservingDuplicate(ByteBuffer b){
ByteOrder holder = b.order();
ByteBuffer ret = b.duplicate();
ret.order(holder);
return ret;
}
这有效,但是有没有实际的方法(泛型可能?)而不必为每个类型(ByteBuffer,FloatBuffer,IntBuffer等)实现这个函数?
答案 0 :(得分:2)
就编译器而言,这些不同类的duplicate
方法之间没有关系;它们不是由任何超类型(超类或接口)定义的。因此,它们唯一的共性是它们的方法签名(名称和参数),而访问它的唯一方法是通过反射。同样适用于order
。这是可能的,但会非常混乱,并且会干扰IDE帮助您查看代码正在执行的操作的能力;它可能不值得。
此外,还有一个更大的问题:您的方法依赖于ByteBuffer#order(ByteOrder)
来设置字节顺序;但是FloatBuffer
和IntBuffer
甚至没有拥有这样的方法。它们有一个order()
,它不带参数并返回它们的字节顺序,但它们没有order(ByteOrder)
,它接受一个字节顺序并采用它。 (这是因为它们的字节顺序实际上不是它们自己的:如果它们是字节缓冲区的包装器,那么它们使用它的字节顺序,如果它们是数组的包装器,它们使用系统的字节顺序。)
所以好消息是。 。 。您不需要为每种类型实现此方法,因为您不能。 :-P
答案 1 :(得分:2)
你可以使用泛型和反射的组合,但它很难看:
public static <T extends Buffer> T endianPreservingDuplicate(T b) throws Exception {
Class<?> clazz = b.getClass();
Method getOrder = getMethod(clazz, "order");
ByteOrder orderTemp = (ByteOrder) getOrder.invoke(b);
Method duplicate = getMethod(clazz, "duplicate");
@SuppressWarnings("unchecked") // cast is safe
T copy = (T) duplicate.invoke(b);
Method setOrder = getMethod(clazz, "order", ByteOrder.class);
setOrder.invoke(copy, orderTemp);
return copy;
}
private static Method getMethod(Class<?> clazz, String name, Class<?>...params) throws NoSuchMethodException {
try {
Method method = clazz.getDeclaredMethod(name, params);
method.setAccessible(true);
return method;
} catch (NoSuchMethodException e) {
Class<?> superclass = clazz.getSuperclass();
if (!superclass.equals(Buffer.class)) {
return getMethod(superclass, name, params);
} else {
throw new NoSuchMethodException("no " + name + " method");
}
}
}
如果没有order()
或duplicate()
的Buffer实现作为b
参数传递,它将抛出异常。
最佳选择是为每种缓冲区类型创建单独的方法。
ruakh的部分信用额度,用于审核代码和建议更新。