Java在兄弟类上调用一个方法

时间:2012-11-27 22:45:38

标签: java

美好的一天,

我尝试了很好的谷歌搜索,甚至一些阅读,但不确定如何继续。这是问题所在:

当我在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等)实现这个函数?

2 个答案:

答案 0 :(得分:2)

就编译器而言,这些不同类的duplicate方法之间没有关系;它们不是由任何超类型(超类或接口)定义的。因此,它们唯一的共性是它们的方法签名(名称和参数),而访问它的唯一方法是通过反射。同样适用于order。这是可能的,但会非常混乱,并且会干扰IDE帮助您查看代码正在执行的操作的能力;它可能不值得。

此外,还有一个更大的问题:您的方法依赖于ByteBuffer#order(ByteOrder)来设置字节顺序;但是FloatBufferIntBuffer甚至没有拥有这样的方法。它们有一个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的部分信用额度,用于审核代码和建议更新。