Java 反射检查传递的对象是否为同一类型

Java reflection check if passed Objects are same type

我有一个 class 比较方法。该方法将两个对象作为参数。 通过 java 反射,我能够获得所有私有和受保护的字段,并通过一些花哨的东西检查它们的 return 类型,并用它们做我想做的事情。

这对我个人来说很好。我知道我想做什么,所以我只比较两个相同类型的对象,仅此而已。

但是......很多人都在使用它......他们有时无法阅读我放在那里的Javadocs和评论以及其他东西所以我必须检查他们是否正在传递相同类型的对象。例如你有: 汽车 a,汽车 b,卡车 a,卡车 b ... 等等...... 我需要检查两个传递的参数是否实际上是相同的类型以进行比较(汽车与汽车,卡车与卡车..)

所以...我不知道这些东西..我是否应该使用反射来列出所有字段的大小,然后检查是否所有字段都具有相同的名称? 或者有更好的解决方案吗?因为如果 fieldsOfA.size 与 fieldOfB.size 相同,则写一些类似的东西......然后如果它们相同则为此循环检查名称看起来有点奇怪..

还有一个问题。 这些对象有一些其他对象的列表——例如 Car 有一个 Wheels 列表。 而且您正在将车轮与其他汽车进行比较。 他们在列表中有 Wheel 1 , Wheel 2 , Wheel 3 , Wheel 4 .. 第二辆车有 Wheel1、Wheel 2、WHeel 4 和 WHeel 3 ..

所以对象是相同的,但只是换了位置..有什么办法可以防止这种情况发生吗?我有一个跟踪代码,可以存储这些对象的每一个差异。所以如果它们有不同的位置,它会给我两个变化。轮子 3 与其他汽车不同,轮子 4 与其他汽车不同。

但他们还是一样... 我不知道如何通过反思解决这个问题……有什么想法吗?

您可以使用 instanceof 运算符。

例如:

public boolean isCar(Vehicle x) {
    if (x instanceOf Car) {
        return true;
    } else {
        return false;
    }

    // note: you can also just do "return x instanceof Car"
}

要比较 类 只需使用 if(object1.getClass() == object2.getClass())

公平地说,不是a.getClass().isInstance(b)就是a.getClass().isAssignableFrom(b),但我总是忘记哪个是哪个。

boolean isInstance(Object obj)
Determines if the specified Object is assignment-compatible with the object represented by this Class.

boolean isAssignableFrom(Class<?> cls)
Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter.

您可能需要第一个。

这听起来像是您在尝试编写一个通用的等于方法。以防万一:请注意,这在一般情况下会失败,因为对象相等并不一定意味着所有字段都相等,甚至所有 public 字段都相等。即使某些字段不同,两个 Java 对象也可能有意相等。给定 class 的两个实例之间的相等性由设计 class 的程序员定义,任何子class 隐含地遵守它们的相等契约。

鉴于此,尝试挖掘对象的超级class' 私有字段通常不是一个好主意。一个更好的主意:super.equals().

因此,假设您编写了 class Truck 来扩展 Vehicle,并且 Truck 定义了两个私有字段 maxLoadhasTrailerHitch。您定义两辆卡车是否相等;假设您需要这两个字段相等。实际上,您可能还希望它们满足 Vehicle 定义的任何相等条件。所以你的 equals 可能看起来像这样:

@Override
public boolean equals(Object obj) {
    // check for type
    if (!(obj instanceof Truck)) return false;
    // check private fields
    Truck other = (Truck)obj;
    if (this.maxLoad != other.maxLoad ||
        this.hasTrailerHitch != other.hasTrailerHitch) return false;
    // check for Vehicle equality
    if (!super.equals(obj)) return false;
    // everything checks out!
    return true;
}

出于显示目的,我写的比实际写的要紧凑一些。理想情况下,检查的顺序无关紧要;我把 superclass 检查放在最后,因为我知道两个私有字段比较运行得非常快,但我不一定知道检查 Vehicles.

涉及什么

注意 instanceof 是如何工作的。如果有人(包括你!)稍后写了 Truck 的 subclass,instanceof 将为真,因此如果他们做与你相同的事情并调用 super.equals(obj),你的 Truck.equals 将检查这两个私有字段,因为它应该。如果您没有 instanceof 检查,而是更严格,请说:

if (obj.getClass().getName().equals("my.pkg.Truck")) // ...

那么 Truck 的子classes 将不会 正确检查这些私有字段。例如,DumpTruck 的两个实例永远不会相等 - 可能不是您想要的。