Aaron
Aaron

Reputation: 151

Test an Object and determine if it is of Class x

I am trying to write a method that will iterate over an ArrayList and then determine if the objects stored inside are either of ClassA or ClassB (these classes Extend class Types), if they are, an int variable (counter) will be incremented and the count of ClassA + ClassB objects will be returned.

I am trying to do something like:

for(Types type : typeList) {
    if( type.getClass().equals(ClassA) || (type.getClass().equals(ClassB) ) {
        counter++;
    }
}
return counter;

However, this is wrong. Any guidance on how to do this is much appreciated. I'm thinking that I could create 'dummy' objects of ClassA and ClassB to compare, however there has to be a better way to do this?

Thanks.

Upvotes: 0

Views: 133

Answers (3)

Paul Draper
Paul Draper

Reputation: 83235

for(Types type : typeList) {
    if( type.getClass().equals(ClassA.class) || (type.getClass().equals(ClassB.class) ) {
        counter++;
    }
}
return counter;

or preferably

for(Types type : typeList) {
    if(type instanceof ClassA || type instanceof ClassB) {
        counter++;
    }
}
return counter;

EDIT: I must point out a difference between these two ways. The first does not count any subclasses of ClassA and ClassB. The second does. For the first, use isInstance instead of equals if you want to count subclasses.

Upvotes: 3

Pr0gr4mm3r
Pr0gr4mm3r

Reputation: 6230

I recommend using the instanceof-operator.

for(Types type : typeList) {
    if( type instanceof ClassA || type instanceof ClassB ) {
        counter++;
    }
}
return counter;

Also note, that if you have null in your list, this approach would still return false. If you use the

type.getClass().equals(ClassA.class)

approach, it will throw a NullPointerException when null is encountered.

Further instanceof and type.getClass().equals(ClassA.class) does not the same thing. Instanceof also returns true, if type is a subclass of either ClassA or ClassB. type.getClass().equals(ClassA.class) evaluates only to true, if type is an instance of ClassA and not one of their subclasses.

Upvotes: 3

Jason C
Jason C

Reputation: 40335

Your original error is because you are referring to the type name itself, not its Class; to get a type's Class object, use .class, e.g.:

type.getClass().equals(ClassA.class)

You can just use instanceof, e.g.:

for (Types type : typeList) {
    if (type instanceof ClassA || type instanceof ClassB) {
        counter ++;
    }
}

By the way, getClass().equals(...) is not equivalent to instanceof; for that you'd want to use ClassA.class.isAssignableFrom(type.getClass()).

Alternatively, if it makes sense semantically, you could have the objects expose properties that determine if they should be counted or not, e.g.:

// Base, for example:
public abstract class Types {
    abstract public boolean isInteresting();
}

// Then: 
public ClassA extends Types { 
    @Override public boolean isInteresting() { return true; }
}

public ClassB extends Types { 
    @Override public boolean isInteresting() { return true; }
}

public ClassC extends Types { 
    @Override public boolean isInteresting() { return false; }
}

// Later:
int countInterestingObjects (ArrayList<Types> typeList) {
    int counter = 0;
    for (Types type : typeList) {
        if (type.isInteresting()) {
            counter ++;
        }
    }
    return counter;
}

Upvotes: 1

Related Questions