Java reflection check if passed Objects are same type

I have a class with compare method. The method takes two objects as arguments. With java reflection I was able to get all the private and protected field and with some fancy stuff check their return types and do what I want to do with them.

This is good for me personaly. I know what I want to do so I just compare two objects of same type and thats all.

BUT ... this is used by many people ...and they sometimes are unable to read a Javadocs and comments and other stuff I put there so I have to check if they are passing object of same type. For example you have : Car a, Car b , Truck a, Truck b ... and so on.. I need to check if the two passed arguments are actually the same type for comparing (Car with car , Truck with truck..)

So ... I dont know the stuff.. Should I use the reflection for listing the size of all fields and then check if all the fields have the same name ? Or is there a better solution ? Becouse writing something like if the fieldsOfA.size is same as fieldOfB.size ... and then for loop for this if they are same to check the names looks kinda weird..

Also another problem. Those objects have lists of some other object - for example Car has a list of Wheels.. And you are comparing the wheels with other car. They have like Wheel 1 , Wheel 2 , Wheel 3, Wheel 4 in list.. and the second car has Wheel1, Wheel 2, WHeel 4 and WHeel 3 ..

So the objects are same , but just have switched positions..is there a way to prevent this ? I have a tracking code that stores every difference in those objects.. So if they have different positions it gives me two changes.. Wheel 3 is different from other car and wheel 4 is different on other car..

But they are still the same ... I don't know how to solve this with reflection ... Any Ideas ?

Upvotes: 1

Views: 2552

Answers (4)

Paul Brinkley
Paul Brinkley

Reputation: 6353

This sounds like you're attempting to write a General Purpose Equals Method. Just in case you are: be aware that this will fail in the general case, because object equality does not necessarily mean all fields are equal, or even that all public fields are equal. It is possible for two Java objects to be intentionally equal even if some fields are different. Equality between two instances of a given class is defined by the programmer designing that class, and anyone subclassing it implicitly abides by their equality contract.

Given that, it's generally a bad idea to attempt to dig out an object's superclass' private fields. A much better idea: super.equals().

So, suppose you write a class Truck that extends Vehicle, and Truck defines two private fields, maxLoad and hasTrailerHitch. You define whether two Trucks are equal; suppose you need both these fields to be equal. In reality, you probably also want them to satisfy whatever equality conditions Vehicle defines. So your equals is likely to look something like this:

@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;
}

I wrote this a bit less compactly than I would in practice, for display purposes. The order of the checks ideally doesn't matter; I put the superclass check last, since I know two private field comparisons runs really fast, but I don't necessarily know what's involved in checking Vehicles.

Notice how the instanceof works. If someone (including you!) writes a subclass of Truck later, the instanceof will be true, and so if they do the same thing you do and call super.equals(obj), your Truck.equals will check those two private fields, as it should. If, instead of an instanceof check, you had been more strict, say:

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

then subclasses of Truck would not get these private fields checked properly. Two instances of, say, DumpTruck would never be equals - probably not what you intend.

Upvotes: 1

cbender
cbender

Reputation: 2251

To compare classes just use if(object1.getClass() == object2.getClass())

Upvotes: 5

Aify
Aify

Reputation: 3537

You can use the instanceof operator.

For example:

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

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

Upvotes: 1

EpicPandaForce
EpicPandaForce

Reputation: 81539

To be fair, it's either a.getClass().isInstance(b) or a.getClass().isAssignableFrom(b) but I always forget which one is which.

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

And

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.

You probably need the first.

Upvotes: 2

Related Questions