Reputation: 1410
I'm wondering if is possible pass types by argument in Java.
Let me explain better:
Suppose the next code
class Bee {
// Class implementation
}
class Worker extends Bee {
// Class implementation
}
class Queen extends Bee {
// Class implementation
}
And now create a container with my bees objects
Vector<Bee> x=new Vector<Bee>();
// ...
for(i=0;i<10;i++)
x.add(new Worker());
// ...
for(i=0;i<10;i++)
x.add(new Queen());
Now I want create a generic method that iterates the vector and returns a set with a specific type of bees, Worker or Queen. How to do this?
I tried
search(x,Worker.class);
static public <T extends Bee> Set<T> search(List<Bee> bees, Class<T> clazz){
// ...
}
and I got an error reporting "The method search(List, Class) is no applicable for the arguments (Set, Class)". The problem is on 2nd argument because the types are incompatible.
Upvotes: 2
Views: 227
Reputation: 114787
From your edit I see, you're still struggling with the implementation. Here is a working example:
public static void main(String[] args) {
Collection<Bee> bees = new ArrayList<Bee>();
bees.add(new Hive.Worker());
bees.add(new Hive.Queen());
Set<Queen> queens = getBeesOfOneType(bees, Queen.class);
}
private static <T extends Bee> Set<T> getBeesOfOneType(Collection<Bee> bees, Class<T> beeType) {
Set<T> result = new HashSet<T>();
for (Bee bee : bees) {
if (beeType.isInstance(bee)) {
// The following cast is safe. The previous if makes sure that
// that bee can be cast to T at this place
T beeTypeInstance = beeType.cast(bee);
result.add(beeTypeInstance);
}
}
return result;
}
There is still one Type safety warning and I'm pretty sure that this one can't be eliminated. The compiler doesn't now, that we select only the T type bees, so it has to warn us.
Upvotes: 5
Reputation: 139931
Use the Class
as an argument to the method
public <T extends Bee> Set<T> filterBeesByType(List<Bee> bees, Class<T> clazz)
by the way, it is a good practice to refer to collection types by their interface (Set
, List
, etc) rather than implementation (Vector
).
Upvotes: 4
Reputation: 114787
Use the instanceof
operator:
public static Set<Queen> queensOnly(Collection<Bee> bees) {
Set<Queen> queens = new HashSet<Queen>();
for (Bee bee:bees) {
if (bee instanceof Queen) {
queens.add((Queen) bee);
}
}
return queens;
}
Upvotes: 3
Reputation: 383776
You can use instanceof
expression to test if a Bee
is a Worker
or a Queen
. You can use this to filter your Vector<Bee>
(or even better, a List<Bee>
) according to the subtypes.
Guava also provides Iterables.filter(Iterable<?> unfiltered, Class<T> type)
that you can use.
Upvotes: 5