Reputation: 2815
Good Day,
I have tried good google searches, and even some reading, but not exactly sure how to proceed. Here is the problem:
When i call duplicate()
on any implementation of java.nio.Buffer, the byte order I had set with the original buffer buf.order(ByteOrder.LITTLE_ENDIAN)
is not preserved. This is a problem. So I set out to create a static method that will allow me to do the following like this example:
public static ByteBuffer endianPreservingDuplicate(ByteBuffer b){
ByteOrder holder = b.order();
ByteBuffer ret = b.duplicate();
ret.order(holder);
return ret;
}
This works, but is there any actual way to do this (generics maybe?) without having to implement this function for every type (ByteBuffer, FloatBuffer, IntBuffer, etc)?
Upvotes: 2
Views: 2041
Reputation: 28697
You could use a combination of generics and reflection, but it's ugly:
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");
}
}
}
It will throw an exception if a Buffer implementation without order()
or duplicate()
is passed as the b
parameter.
The best option is to make individual methods for each buffer type.
Partial credits to ruakh for reviewing the code and suggesting updates.
Upvotes: 2
Reputation: 183446
So far as the compiler can tell, there is no relationship between the duplicate
method on these various classes; they're not defined by any supertype (superclass or interface). Their only commonality, therefore, is in their method signature (name and parameters), and the only way to access that is via reflection. And similarly for order
. This would be possible, but would be very messy, and would interfere with your IDE's ability to help you see what your code is doing; it's probably not worth it.
Furthermore, there's an even bigger problem: your method depends on ByteBuffer#order(ByteOrder)
to set the byte order; but FloatBuffer
and IntBuffer
don't even have such a method. They do have an order()
that takes no arguments and returns their byte order, but they don't have an order(ByteOrder)
that takes a byte order and adopts it. (This is because their byte order isn't really their own: if they're wrappers around a byte buffer, then they use its byte order, and if they're wrappers around arrays, they use the system's byte order.)
So the good news is . . . you don't need to implement this method for every type, because you can't. :-P
Upvotes: 2