在Java中工作,假设我有两个对象,感谢obj.getClass().isArray()
,我知道这两个对象都是数组。让我们进一步说,我想将这两个数组相互比较 - 可能是使用Arrays.equals
。是否有一种优雅的方式来做到这一点,而不诉诸一个大的详尽的if / else树来找出需要使用哪种Arrays.equals
的味道?我正在寻找的东西不像这样:
if (obj1 instanceof byte[] && obj2 instanceof byte[]) {
return Arrays.equals((byte[])obj1, (byte[])obj2);
}
else if (obj1 instanceof boolean[] && obj2 instanceof boolean[]) {
...
答案 0 :(得分:8)
您可以使用反射。
public static boolean arrayEquals(Object arr1, Object arr2) throws Exception {
Class<?> c = arr1.getClass();
if (!c.getComponentType().isPrimitive()) {
c = Object[].class;
}
Method m = Arrays.class.getMethod("equals", c, c);
return (Boolean) m.invoke(null, arr1, arr2);
}
反射仅用于在运行时找到正确的方法,而没有你想要避免的眼睛;实际的Arrays.equals
方法应该运行得非常快。
显然,生产版本需要更强大的异常处理。对于非原始数组,您可能还希望使用deepEquals(Object[], Object[])
而不是equals(Object[], Object[])
。
答案 1 :(得分:2)
我担心唯一的选择是使用反射,这几乎就是丑陋。
Arrays.getClass()
.getMethod("equals", new Class[]{obj1.getClass(), obj2.getClass()})
.invoke(null, new object[]{obj1, obj2});
未经测试,可能会以各种方式失败,需要大量的异常处理......
答案 2 :(得分:0)
也许Strategy Pattern可以帮助它看起来更好:)
答案 3 :(得分:0)
您可以使用不getClass()
的{{1}}方法;看看这个例子:
isArray()
我事先承认这远不是一个完美的解决方案。它缩短了你在原帖中可能存在的巨大if-else链,但如果类型不一样会导致错误。以下类似的代码甚至不能在MyEclipse 8.0中编译:
byte[] foo = { 1, 2 };
byte[] bar = { 1, 2 };
System.out.println(foo.getClass());
System.out.println(bar.getClass());
if(foo.getClass() == bar.getClass())
System.out.println(Arrays.equals(foo, bar));
如果您确信自己不会出现类型不匹配问题,并且您唯一的问题是您不想找出您拥有的类型,那么这可能会有效。
答案 4 :(得分:0)
您可以使用枚举策略模式为每种类型创建比较器:
public enum ArrayEq {
BYTE_PRIMITIVE(Byte.TYPE) {
protected boolean doEquals(Object array1, Object array2) {
return Arrays.equals((byte[]) array1, (byte[]) array2);
}
},
... enum element for each component type
private final Class<?> type;
private ArrayEq(final Class<?> type) { this.type = type; }
public Class<?> getComponentType() { return type; }
// force all enums to implement this method
protected abstract boolean doEquals(Object array1, Object array2);
public static boolean equals(Object array1, Object array2) {
if(array1 == null) return array2 == null;
// you need to populate this map in a static initializer of the enum
// a simple linear search would work too since the number of elements is small
typeToElementMap.get(array1.getComponentType())
.doEquals(array1, array2);
}
}
忽略错误处理,当然,你想在传递错误类型的地方抛出IllegalArgumentException(我更喜欢让ClassCastException生成JVM,并在我检测到错误时在我自己的代码中抛出IAE。)
答案 5 :(得分:-1)
你试过这个吗?
// Test if both arrays are of the same type
if (array1.class.getComponentType.equals(array2.class.getComponentTYpe)) {
// Polymorphism FTW !
return Arrays.equals(array1, array2);
}