I want to run certain tests in Lists. The Lists can contain entirely different classes.
I have one method to check the consistency of the list - not null, not empty, no more than x elements. This is common to all the lists. Then I want to test each of the objects, using overloading.
The idea would be something like:
public static <T> void check(List<T> list) {
//do general checks
for (T element : list) {
check(element);
}
}
and then
public static void check(SomeType element) {...}
public static void check(SomeOtherType element) {...}
But I also had to add a method like this:
public static void check(T element) {...}
And this was called at runtime - not my other methods with the specific classes. Although the class was exactly the same. I'm evidently missing some generics understanding.
Now if I don't use the general method at all and try to solve it this way:
public static void check(List<SomeType> list) {...}
public static void check(List<SomeOtherType> list) {...}
Compiler error - "Method check(List) has the same erasure check(List) as another method..."
So is there any elegant solution for this? I could just use different method names but would like to know how it's possible without that.
Thanks!
This isn't something about generics that you're missing. Java does not have double dispatch. The call to check must be resolved at compile-time, and check(T) is the only match since the compiler can't tell if T is SomeType or SomeOtherType in a given scenario. It needs to choose one method to call that will work for all possible Ts.
This is sometimes solved using the visitor pattern.
The problem should be solved by the caller. When it instanciate your class with a concrete type for T, it should also pass an instance of Checker<T> with the same concrete type:
public class SomeClass<T> {
private List<T> list;
private Checker<T> checker;
public SomeClass(Checker<T> checker) {
this.checker = checker;
}
public void check() {
checker.check(list);
}
}
public interface Checker<T> {
public void check(List<T> list);
}
...
SomeClass<Foo> someClass = new SomeClass<Foo>(new Checker<Foo>() {
#Override
public void check(List<Foo> list) {
// do whatever you want here
}
});
You can use instanceof to dispatch:
public static <T> void check(List<T> list) {
for (T element : list) {
check(element);
}
}
public static void check(T t) {
if (t instanceof SomeType) {
SomeType someType = (SomeType) t;
// code for SomeType ...
} else if (t instanceof OtherType) {
OtherType otherType = (OtherType) t;
// code for OtherType ...
} else {
// we got a type that we don't have a method for
}
}
With generics, the type parameter is actually erased during compilation, and the list object don't know anything about the static type of the object it contains. Since it doesn't know it, it can not use overloading to call methods with different parameters, because Java doesn't support multiple dispatch.
You have then three choices:
Make your objects implement a Checked interface with a check method that does the check logic. Downside is that the check logic is now dispersed in several places and it is not practical if you have objects of classes you don't have control of.
Use instanceof to call explicitly the check methods according to the dynamic type of the object. Downside is you potentially end up with a big if/else block a bit harder to maintain.
Implement the visitor pattern. Downside is that you have to change the object classes too, but the check logic stay in a single place.
Since the type of the variable is lost in check(List<T> list) you have two options:
1. Do different things by checking runtime type
check(T element) {
if (element.getClass().equals(SomeType.class)) {
check((SomeType) element);
} elseif (element.getClass().equals(SomeOtherType.class)) {
check((SomeOtherType) element);
}
This can be made a little more sophisticated, for example by wrapping each check in a Callable and using a Map<Class, Callable>
This is similar to visitor pattern.
2. Calling a virtual method on the element to be checked itself
If the checking logic can be pushed to the object to be checked itself (this is not necessarily a bad thing) then you don't need to check types:
interface Checkable { void check(); }
class SomeType implements Checkable { .... }
class SomeOtherType implements Checkable { .... }
Then:
public static <T extends Checkable> void check(List<T> list) {
for (T element : list) {
element.check();
}
}
These are the only two options, any implementation has to be a variation on one of these
Related
Consider the following:
public class Doer {
public static void doStuff(A a) {
System.out.println("a");
}
public static void doStuff(B b) {
System.out.println("b");
}
}
Where B extends A
And a generic class like this:
public class NewClass<T extends A> {
public void doSomething(T entity) {
Doer.doStuff(entity);
}
}
If I call this method as follows it prints "a"
new NewClass<B>().doSomething(new B());
How do I get it to print "b" ?
Thanks in advance
Edit: A dirty solution is to change
Doer.doStuff(entity);
to
if(entity instanceof B){
Doer.doStuff((B) entity);
}else {
Doer.doStuff(entity);
}
But I'm looking for a solution that does not use instanceof and so that I don't have to add an extra if (C intance of A) ... to NewClass when I make a new Class extending A
See these questions for answers: Java Generic / Type Dispatch Question, How does Java method dispatch work with Generics and abstract classes?
Basically, you have these options:
define doStuff as an abstract method on A
try the Visitor pattern
if possible, use a language (e.g. Xtend) that supports dynamic dispatch
Java doesn't do dynamic binding based on the argument type. The actual method that is invoked is determined at compile time. So in case of a generic type, the method with Object as the parameter type will be invoked.
You could work around this by checking the type with instanceof, but the puristic way of handling this is to leverage polymorphism and using Double Dispatch. But that is not always an option, since it tightly couples your calling class and your argument class together.
I think that in that case you're forced to actually determine entity's type and cast it, as your function doSomething just infers that entity inherits from A.
Basically you could do:
public void doSomething(T entity) {
if (entity instanceof B) {
Doer.doStuff((B) entity);
}
else {
Doer.doStuff(entity);
}
}
NewClass would have to have two methods also, or you could do something like this:
public class NewClass<T extends A> {
public void doSomething(T entity) {
if(entity instanceof B){
Doer.doStuff((B)entity);
}else if(entity instanceof A){
Doer.doStuff((A)entity);
}
}
}
I don't understand the following code:
public class EventAdapter extends ArrayAdapter<Event>
{
public EventAdapter(Context context, int textViewResourceId,
List<Event> objects)
{
super(context, textViewResourceId, objects);
this.resource = textViewResourceId;
}
}
I am confused about the <Event> part in both cases. I understand it has something to do with Generics, but I don't understand it. I read http://docs.oracle.com/javase/tutorial/java/generics/, but still don't understand.
I do understand that objects is an ArrayList of objects of the type Event.
The part I don't understand is extending an ArrayAdapter with the Type <Event>. What does this signify?
extends ArrayAdapter<Event>
The type restriction here will influence on the return types of methods in the class, and the argument types of methods.
Here is an example, if you have a class:
class SomeClass<T> {
protected T value;
public void setValue (T value) {
this.value = value;
}
public T getValue () {
return value;
}
}
And if you have another class:
class SubClass extends SomeClass {
#Override
public void setValue (Event value) { // Fail! It is not overriding the super class' method.
this.value = value; // Warning! Unchecked types (maybe inconsistent).
}
}
If you remove the #Override annotation, it will run. But the extends SomeClass is useless and might cause problem if you keep it there -- there will be two very similar methods: setValue(Event) and super.setValue(T). Now the question is will the subclass have access to the super.setValue(T) method? I will explain it in the end, see "A missing type parameter bounding example".
So, you need to specify the type in declaration:
class SubClass extends SomeClass<Event> {
#Override
public void setValue (Event value) { // Correct now!
this.value = value;
}
}
Also, if you declare an inconsistent type:
class SubClass extends SomeClass<String> {
#Override
public void setValue (Event value) { // Fail! Not overriding.
this.value = value; // Fail! Inconsistent types.
}
}
So the type restricts the behavior of class body.
A missing type parameter bounding example:
import java.lang.reflect.*;
class Super<T> {
public void method (T t) {
System.out.println("Hello");
}
public void method2 () {
}
}
public class Test extends Super {
/*public void method (Object t) {
System.out.println("world");
}*/
/*public <T> void method (T t) {
}*/
public static void main (String args[]) {
new Test().method("");
for (Method m : Test.class.getMethods()) {
System.out.println(m.toGenericString());
}
}
}
If I comment method() in the subclass, it is compiled with a warning: Test.java uses unchecked or unsafe opertations. In the running result, it turned the generic type T into Object: public void Test.method(java.lang.Object).
If I only uncomment the first method() in the subclass, it is compiled with no warnings. In the running result, the subclass owns one public void Test.method(java.lang.Object). But it doesn't allow #Override annotation.
If I only uncomment the second method() in the subclass (which also has a generic type bounding), the compile fails with an error: name clash. It also doesn't allow #Override annotation. If you do so, it throws a different error: method does not override.
method2() is inherited by the subclass unanimously. But you also can't write the following code:
in superclass: public void method2 (Object obj) and in subclass: public <T> void method2 (T obj). They are also ambiguous and is not allowed by the compiler.
Here's my simplistic way of looking at generics in this case. Given the definition:
public class EventAdapter extends ArrayAdapter<Event>
I read it as: "An EventAdapter IS-A ArrayAdapter OF Event objects."
And I take List<Event> objects to mean a List of Event objects.
Collections are containers for objects, while Generics define what they can contain.
This assigns a value for the generic parameter in ArrayAdapter in a way that takes away control from the user of the EventAdapter class.
Any method overriding here can then replace T with Event and Event can be used inplace of T without casts.
This is the general definition of generics.
That this is allowed in this case is defined in the spec. While the exact behaviour is not defined in that section I think it is in line with all other generic behaviour as far as I can see.
While I see the construct here the first time, after some thinking it really isn't anything unusual.
I have a set of POJOs with a common superclass. Those are stored in a two-dimensional array of type superclass. Now, I want to obtain an object from the array and use methods of the subclass. This means I have to cast them to the subclass. Is there a way to do this without using instanceof?
Update: As a concrete example: http://obviam.net/index.php/the-mvc-pattern-tutorial-building-games/ See: "Add new actions (attack) when an enemy is clicked"
Yes - you can do it by inverting the flow: instead of your code doing something when the instance of the base class is of a specific type, pass an action item to the object, and let the object decide whether to perform it or not. This is the basic trick behind the Visitor Pattern.
interface DoSomething {
void act();
}
abstract class AbstractBaseClass {
abstract void performAction(DoSomething ds);
}
class FirstSubclass extends AbstractBaseClass {
public void performAction(DoSomething ds) {
ds.act();
}
}
class SecondSubclass extends AbstractBaseClass {
public void performAction(DoSomething ds) {
// Do nothing
}
}
AbstractBaseClass array[] = new AbstractBaseClass[] {
new FirstSubclass()
, new FirstSubclass()
, new SecondSubclass()
, new FirstSubclass()
, new SecondSubclass()
};
for (AbstractBaseClass b : array) {
b.performAction(new DoSomething() {
public void act() {
System.out.println("Hello, I'm here!");
}
});
}
If you know they're of the subclass type, then just cast them directly without an instanceof check.
But putting them in a superclass-typed array is telling the compiler to discard the information that they're actually of the subclass type. Either your superclass should expose those methods (perhaps as abstract), or your array should be of the subclass type (so you're not telling the compiler to forget the actual type of the objects), or you'll have to suck it up and do the cast (possibly with the instanceof test).
The only other notable alternative is that you might experiment with the visitor pattern, which passes an action to the object and lets the object decide what to do with it. That lets you override classes to ignore or perform the actions based on their runtime type.
You can try to use the Visitor design pattern.
http://en.wikipedia.org/wiki/Visitor_pattern
You have to ask yourself, why do you need to know their type, maybe this can be replaced with the use of an abstract method in the super class, that every one of them can implement according the desired result.
abstract class A{
abstract void visit();
}
class B extends A{
void visit() { print("B"); }
}
class C extends A {
void visit() { print("C"); }
}
I would avoid casting them in the first place.
Really think about what you're trying to do, and if they should be in the same collection like that.
If you have something like this
for(MyObj o : array) {
if(o instanceof A) {
((A)o).doA();
}
if(o instanceof B) {
((B)o).doB();
}
}
consider this instead
abstract class MyObj {
abstract void doIt();
}
class A {
void doIt() { doA(); }
}
class B {
void doIt() { doB(); }
}
Expose the method in the superclass, and then use overriding. Provide an empty implementation in the base class so that subclasses can ignore the action if needed.
Hello I'm wondering what would be some more elegant alternatives to something like this:
class Base...
class A extends Base...
class B extends Base...
//iterator of colection containing mixed As and Bs i want to remowe Bs and do omething with As
while(iterator.hasNext()) {
Base next = iterator.next();
if(next instanceof A) // do something
if(next instanceof B)
iterator.remove();
}
Sow what are the alternatives...
Thank you for advices.
edit: Base class may have many subclasses not just two and their numbers may grow in time
You can create methods in Base and override them in A and B.
For example:
class Base{
public boolean shouldRemove(){
return false;
}
public void doSomething(){
}
}
class A extends Base{
#Override
public void doSomething() {
}
}
class B extends Base{
#Override
public boolean shouldRemove() {
return true;
}
}
and then you don't need know what class the object is an instance of:
while(iterator.hasNext()) {
Base next = iterator.next();
if(next.shouldRemove()){
iterator.remove();
}
else{
next.doSomething();
}
}
Do you really need to remove them from the list? Why don't you just have the method to do something in the Base class (doing nothing) and then just override it do to what you want on class A.
class Base{
public void doSomething(){
}
}
class A extends Base{
#Override
public void doSomething(){
// do something
}
}
Then you could just iterate over the list and calling the method doSomething on all objects.
for(Base base : list) {
base.doSomething();
}
This way only the classes that have overridden the doSomething() method will actually do something. All the other classes will just execute the dummy implementation in the Base class.
If Base was an abstract class you could declare the doSomething() as abstract and have the extending classes implement it. With this approach all classes would have to implement the method and classes for which you don't want any computation to be performed you would just provide a dummy implementation of that method. Alternatively you could even create an interface with the doSomething() method and have (which could even be a better decision) and have the Base class implement it, given that only the extending classes would actually implement the method.
instanceof is a good way to filter objects by type - and that's what you want to do. You have a mixed collection and so you need some kind of filter, either filter the input (store nothing but As) or filter the output (process nothing but As).
If you just don't like "instanceof", you could use an enum to specify the type and add a final method to get the type at Base:
enum Type { ATYPE, BTYPE };
public Base {
final private Type type;
public Base(Type type) { this.type = type; }
public Type getType() { return type; }
// ...
}
public A {
public A() { super(Type.ATYPE); }
}
while(iterator.hasNext()) {
Base next = iterator.next();
switch (next.getType) {
case ATYPE: // do something and break
case BTYPE: iterator.remove(next); break;
}
}
i think is very short and clear solution and has no alternatives (without code growing),
just add else if instead of if in second case
Also you can split code on function calls, and if statement will not be huge
Another solution is to create Map of delegates that will be called. Like this:
interface ISimpleDelegate{ void doSomeLogic(Base b) }
`Map delegates = new HashMap();
After this add your logic as anonymous classes that realizes ISimpleDelegate.
delegates.put(A.class, new ISimpleDelegate() { //write your logic here });
I hope that the idea is clear
And in your loop you just call delegates:
while(iterator.hasNext()) {
Base next = iterator.next();
delegates.get(next.getClass()).doSomeLogic(next);
}
In general, a nice solution to avoid instanceof is to use the so-called visitor pattern.
For this pattern, you need an additional interface (the Visitor), an implementation of it that contains the code you want to execute and an additional method in all classes of your hierarchy, so this might be overkill in small cases (but it is very handy if there is not only A and B, but more types).
In your case it would look like this:
interface Visitor {
void visit(A a);
void visit(B b);
}
class Base {
abstract accept(Visitor v);
}
class A extends Base {
accept(Visitor v) {
v.visit(this);
}
}
class B extends Base {
accept(Visitor v) {
v.visit(this);
}
}
class MyVisitor implements Visitor {
visit(A a) {
doSomethingWithA(a);
}
visit(B b) {
doSomethingWithB(b);
}
}
It is used like this:
MyVisitor v = new MyVisitor();
while(iterator.hasNext()) {
Base next = iterator.next();
next.accept(v);
}
An advantage is that you have to write most of the code only once. If you want to do other things with A and B in another place of your program, just write another implementation of Visitor. You don't need to modify Base, A and B as you would if you'd add doSomething() to these classes.
Edit:
If the number of sub-classes increases, you need to change all your existing implementations of Visitor. However, at least the compiler tells you about that. With instanceof you might end up forgetting a place where you need to add a handling clause. This can at most be detected at runtime, whereas the visitor pattern gives you compile-time safety.
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?
EDIT
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.
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.
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.
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).
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;
}