我有一个类比较方法。该方法接受两个对象作为参数。使用java反射,我能够获得所有私有和受保护的字段,并使用一些花哨的东西检查它们的返回类型,并对它们做我想做的事情。
这对我个人有好处。我知道我要做什么,我只是比较两个相同类型的对象,仅此而已。
但是…很多人都用这个…它们有时无法读取Javadocs和注释以及我放在那里的其他东西,所以我必须检查它们是否传递相同类型的对象。例如你有:汽车a,汽车b,卡车a,卡车b……等等......我需要检查传递的两个参数是否实际上是相同类型的比较(Car与Car, Truck与Truck ..)
所以…我不知道这些东西……我是否应该使用反射来列出所有字段的大小,然后检查所有字段是否具有相同的名称?还是有更好的解决方案?因为写一些像fieldsOfA。大小与fieldOfB相同。大小……然后for loop for this如果它们是相同的来检查名字看起来有点奇怪。
还有一个问题。这些对象有一些其他对象的列表——例如Car有一个Wheels的列表。你在和别的车比较轮子。他们有1号轮,2号轮,3号轮,4号轮…第二辆车有轮子1、轮子2、轮子4和轮子3。
所以对象是相同的,但只是交换了位置…有没有办法防止这种情况?我有一个跟踪代码,可以存储这些对象的每一个差异。所以如果他们的位置不同,我就有两个变化。3号轮不同于其他车,4号轮不同于其他车。
但他们仍然是一样的…我不知道如何用反思来解决这个问题……有什么想法吗?
使用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.
你可能需要第一个
您可以使用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"
}
这听起来像是在尝试编写一个通用的Equals方法。以防万一:请注意,这在一般情况下会失败,因为对象相等并不一定意味着所有字段都相等,甚至不意味着所有公共字段都相等。即使某些字段不同,也可以故意使两个Java对象相等。给定类的两个实例之间的相等性是由设计该类的程序员定义的,任何子类化该类的人都隐式地遵守它们的相等性契约。
考虑到这一点,试图挖掘对象的超类的私有字段通常是一个坏主意。一个更好的主意:super.equals()
.
maxLoad
和hasTrailerHitch
。定义两个truck是否相等;假设您需要这两个字段相等。实际上,您可能还希望它们满足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;
}
出于显示的目的,我把写得比实际情况稍微宽松一些。理想情况下,检查的顺序并不重要;我把超类检查放在最后,因为我知道两个私有字段比较运行得非常快,但我不一定知道检查车辆涉及什么。
注意instanceof是如何工作的。如果有人(包括您!)稍后编写了Truck的子类,instanceof将为真,因此,如果他们做与您相同的事情并调用super.equals(obj)
,您的Truck.equals
将检查这两个私有字段,就像它应该做的那样。如果您没有进行instanceof
检查,而是进行了更严格的检查,请说:
if (obj.getClass().getName().equals("my.pkg.Truck")) // ...
则Truck的子类将不能正确检查这些私有字段。例如,DumpTruck
的两个实例永远不会相等——可能不是您想要的。