I'm relatively new to Java and would appreciate any help regarding the following inquiry. I've defined two classes - for simplicity sake, let's call them A
and B
. Class A
has a method named methodA
, and Class B
has a method named methodB
. The objects of these two classes are contained in an ArrayList
called container
. What I need to do is to loop over the ArrayList
and call different methods depending on the type of object.
This is my code currently:
for (Object item : container) {
if (item instanceof A) {
item.methodA()
} else if (item instanceof B) {
item.methodB()
}
}
My IDE (NetBeans) won't compile the above code since item
of type Object
doesn't have methodA
or methodB
. Is there some other way to write the loop to accomplish what I need it to do? Thanks.
You need to add a cast. Just because you checked that item is an instance of A (or B) doesn't allow you to call A methods on the item.
if (item instanceof A) {
((A) item).methodA();
} else if (item instanceof B) {
((B) item).methodB();
}
In general, though, you may want to consider restructuring your code to avoid this pattern. For example, you could create a common interface of base class which both A and B implement:
public interface MyInterface {
void doSomething();
}
class A : MyInterface {
...
public void doSomething() { this.methodA(); }
}
class B : MyInterface {
...
public void doSomething() { this.methodB(); }
}
Then you could do:
List<MyInterface> list = // a list of A's and B's
for (MyInterface item : list) {
// use polymorphism to invoke the appropriate method
item.doSomething();
}
The visitor pattern is another common solution for this type of code which is useful when you want to support a bunch of different common operations across a fixed set of classes without constantly modifying those classes.
You are dealing with the variants problem, for which Java (and pretty much any other widely-used language) has no good answer. Scala solves it with case classes, and more academic languages like ML handle it with ease.
All the above answers suggest using if-ladders and casting, which is the tersest solution in Java but which basically gives up complete compile-time safety. If you don't like casts, you can use a visitor pattern to get around the issue. It's about as verbose as you can get, but it's completely type-safe.
interface ABVariantVisitor {
void visit( A a );
void visit( B b );
}
interface ABVariant {
void accept( ABVariantVisitor v );
}
class A implements ABVariant {
// ...
void accept( ABVariantVisitor v ) {
v.visit( this );
}
// ...
}
class B implements ABVariant {
// ...
void accept( ABVariantVisitor v ) {
v.visit( this );
}
// ...
}
List< ABVariant > container;
// ...
for ( ABVariant item : container ) {
item.accept( new ABVariantVisitor() {
@Override void visit( A a ) {
a.methodA();
}
@Override void visit( B b ) {
b.methodB();
}
} );
}
Just do type casting to A or B before calling method on it.Convert item into A or B before calling the method
for (Object item : container) {
if (item instanceof A) {
((A) item).methodA();;
} else if (item instanceof B) {
((B) item).methodB();
}
}
Try in this way
if (item instanceof A) {
((A) item).methodA();
} else if (item instanceof B) {
((B) item).methodB();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.