Java dynamic adapter - java

I'm using some Java code which produces the following interfaces. This code is non-modifiable.
interface A1 {
public void run();
}
interface A2 {
public void run();
}
...
interface A24 {
public void run();
}
I'm having a class cast error with the following code. How would I dynamically build an adapter to my interface?
interface ARunnable {
public void run();
}
public void someMethod() {
// getARunnables() returns a list of A1, A2, ... A24
List<ARunnable> runnables = (List<ARunnable>)getARunnables();
for (ARunnable a : runnables) {
a.run();
}
}

Since the interfaces can't be modified to extend java.lang.Runnable, an option would be to use java.lang.reflect.Proxy to build up instances of Runnable that delegate to your A1, A2... interfaces.
It's not trivial, but take a look at this example using java.lang.reflect.Proxy. The sample simply delegates to a delegate object based on method name.
public class ProxyTest
{
public static void main(String... args)
{
List<?> instances = Arrays.asList(new A1());
List<ARunnable> runnableInstances = new ArrayList<ARunnable>(instances.size());
for (Object instance : instances)
{
ARunnable runnableInstance = (ARunnable)Proxy.newProxyInstance(
ARunnable.class.getClassLoader(),
new Class<?>[] {ARunnable.class},
new RunnableWrapper(instance));
runnableInstances.add(runnableInstance);
}
//Now we have a list of ARunnables!
//Use them for something
for (ARunnable runnableInstance : runnableInstances)
{
runnableInstance.run();
}
}
private static class RunnableWrapper implements InvocationHandler
{
private final Object instance;
public RunnableWrapper(Object instance)
{
this.instance = instance;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
//Ensure that your methods match exactly or you'll get NoSuchMethodExceptions here
Method delegateMethod = instance.getClass().getMethod(method.getName(), method.getParameterTypes());
return(delegateMethod.invoke(instance, args));
}
}
public static class A1
{
public void run()
{
System.out.println("Something");
}
}
public static interface ARunnable
{
public void run();
}
}
Also I would recommend you fix the line
List<ARunnable> runnables = (List<ARunnable>)getARunnables();
That type safety warning you should not ignore. That list of objects does not actually contain ARunnables, hence the ClassCastException.

Consider this sample code (doesn't have the loop for simplicity):
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
interface Interface {
public void run();
}
static class Hello /* does't implement Interface */{
public void run() {
System.out.println("Hello, world!!");
}
}
static <T> T dirtyCast(Class<T> intrface, final Object target) {
return intrface.cast(Proxy.newProxyInstance(
intrface.getClassLoader(),
new Class<?>[] { intrface }, new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
Method targetMethod = target.getClass().getMethod(
method.getName(), method.getParameterTypes());
return targetMethod.invoke(target, args);
}
}));
}
public static void main(String[] args) {
Interface proxy = dirtyCast(Interface.class, new Hello());
proxy.run();
}
}
Please don't consider this solution as feasible if you want to pass arguments or return values or throw exceptions. The problem is that the shared objects (as arguments and return values and exceptions) need to live in the same (common) classloader. This also means that usual java lang types and exceptions will be okay.
Also you have to bear in mind security considerations. Classloaders may have different (incompatible) security constraints.
If you run quickly into trouble, I would try a project designed for this like transloader.
Have fun.

In your case you can use simply
public void someMethod() throws ReflectiveOperationException {
// getARunnables() returns a list of A1, A2, ... A24
List runnables = (List)getARunnables();
for (Object r : runnables) {
r.getClass().getMethod("run").invoke(r);
}
}

Related

How to create constructor in java parameterized with class?

I want to have a class to run other classes in java, like constructor parameterized with a class to run that class later on, similar to this
class MyClass{
Class classToRun;
public MyClass(Class c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
where classToRun possible classes doesn't have a common ancestor, but all have method someStaticMethod, and have no idea about MyClass, which runs them.
But there are problems, like inner classes cannot have static methods, classes cannot be cast Class, etc.
There are solutions for parameterized with class methods, like
How do I pass a class as a parameter in Java?
Passing a class as an argument to a method in java
but not for constructors.
What is the proper solution to do this?
Use lambdas and pass the method reference: they match on the method signature. For void someStaticMethod() you can use Runnable.
class MyClass{
private final Runnable methodToRun;
public MyClass(Runnable someStaticMethod) {
methodToRun = someStaticMethod;
}
public void runClass(){
methodToRun.run();
}
}
new MyClass(SomeClass::someStaticMethod).runClass();
You cannot enforce that the method passed has the right name, but looks even neater IMHO.
You need to understand what generics are.
interface
public interface SomeInterface {
void someStaticMethod();
}
use
class MyClass<T extends SomeInterface>{
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
As 2 of 3 answers were not to the point, I decided to publish fixed versions of both answers as far as they can be fixed.
The f1sh version from the above should like follows:
public class ClassToRunOthers {
Class classToRun;
public ClassToRunOthers(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
public static void main(String[] args) throws Exception {
ClassToRunOthers mc = new ClassToRunOthers(SomeClass.class);
mc.runClass();
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
The zwei solution above can not be fixed without reflection, as generics is not to the point. Evan if you try to parametrize not with SomeInerface (because SomeClass does not extend a common SomeInterface), but with Object, it is still won't solve the problem:
public class MyClass<T extends Object> {
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass() {
// classToRun.someStaticMethod(); // Cannot resolve method 'someStaticMethod' in 'T'
}
public static void main(String[] args) {
MyClass mc = new MyClass(SomeClass.class);
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
This can be fixed like the above, via reflection.
I believe, it can be done with annotations in some elegant way, and may be someone will share us with such a solution or I will do it by myself as time permits.
By now for myself, a solution with saving class name in the String in constructor next day after the question been asked did the trick.
You will have to use reflection if you want to execute a method when you only have the Class instance.
In the code below, runClass finds the method of the class using it's name as a String, then executes it. This code assumes that the method is static, also ignoring any Exception handling.
The following code prints "test":
class MyClass {
Class classToRun;
public MyClass(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
}
class Main {
public static void main(String[] args) throws Exception {
MyClass mc = new MyClass(Main.class);
mc.runClass();
}
static void someStaticMethod() {
System.out.println("test");
}
}

How to avoid duplicated if statements

I have multiple services that implement interface with one method - execute(). Each service uses this method to execute some actions based on a String value, which, in original code, is enum, so those values are constants.
interface Service{
public void execute();
}
class Service1 implements Service{
//constructors
public void execute(JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
doSomething(payload);
}
}
}
class Service2 implements Service{
//constructors
public void execute(JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
doSomething1(payload);
}
if(payloadType.equals("type2")){
doSomething2(payload);
}
}
}
I want to avoid writing same if statements each time I create a new Service. Problem is, that each Service doesn't have to execute actions based on each string types. So Service1 executes action when type is equal to "type1", however Service2 executes actions based on "type1" and "type2".
I tried following solution:
class Main {
public static void main(String[] args) {
exec(new B(), "type2");
}
private static void exec(Service service, JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
Init i = (Init)service;
i.init(payload);
}
if(payloadType.equals("type2")){
Action a = (Action)service;
a.action(payload);
}
}
}
interface Service{
}
interface Init{
public void init(JSONObject payload);
}
interface Action{
public void action(JSONObject payload);
}
class A implements Service, Init{
#Override
public void init(JSONObject payload){
doSomething(payload);
}
}
class B implements Service, Init, Action{
#Override
public void init(JSONObject payload){
doSomething1(payload);
}
#Override
public void action(JSONObject payload){
doSomething2(payload);
}
}
The above code works, but I don't like using casting. I think it's not a good practice, also very unsafe. Could you suggest, what design pattern or other solution could I use here? I tried visitor, but I couldn't figure out the right implementation with this case.
UPDATE
Thanks for all the answers, they were very helpfull. I managed to achieve what I was looking for. Here's the code that finally works.
public class Main {
public static B b = new B();
public static A a = new A();
public static void main(String[] args) {
exec(b, "init");
}
private static void exec(Service service, String type){
if(type.equals("init") && service instanceof Init){
service.fillCarrier(new InitCarrier());
}
if(type.equals("action") && service instanceof Action){
service.fillCarrier(new ActionCarrier());
}
}
}
interface Carrier<T>{
public void set(T t);
}
class InitCarrier implements Carrier<Init>{
public void set(Init init){
init.init();
}
}
class ActionCarrier implements Carrier<Action>{
public void set(Action action){
action.action();
}
}
abstract class Service{
public void fillCarrier(Carrier carrier){
carrier.set(this);
}
}
interface Init{
public void init();
}
interface Action {
public void action();
}
class A extends Service implements Init{
#Override
public void init(){
System.out.println("init a");
}
}
class B extends Service implements Init, Action{
#Override
public void init() {
System.out.println("init b");
}
#Override
public void action(){
System.out.println("action");
}
}
To achieve this requirement, we need to pattern.
Factory pattern.
Strategy pattern.
TypeFactory creates an object based on the string we delivered. Each Type implementation implements a doSomething() method in its own way. (factory pattern is used here)
Type Strategy:
interface Type{
public void doSomething();
}
class TypeOne implements Type{
#Override
public void doSomething() {
System.out.println("Type One!");
}
}
class TypeTwo implements Type{
#Override
public void doSomething() {
System.out.println("Type Two!");
}
}
Type Factory:
class TypeFactory{
Type type;
public Type createType(String condition) {
if (condition == null || condition.isEmpty()) {
return null;
}
if ("type1".equals(condition)) {
return new TypeOne();
}
else if ("type2".equals(condition)) {
return new TypeTwo();
}
return null;
}
}
Now to achieve the final goal, we need to declare a Service interface with an execute method. This execute method takes Type as an input parameter. Based on which type you actually pass, the corresponding doSometing method will be invoked. (strategy pattern used only)
interface Service{
public void execute(Type type);
}
class ServiceOne implements Service{
#Override
public void execute(Type type) {
System.out.print("Service One - ");
type.doSomething();
}
}
class ServiceTwo implements Service{
#Override
public void execute(Type type) {
System.out.print("Service Two - ");
type.doSomething();
}
}
Main Class looks like this:
public class DesignPatternCombo {
public static void main(String[] args) {
Type typeOne = new TypeFactory().createType("type1");
Type typeTwo = new TypeFactory().createType("type2");
Service serviceOne = new ServiceOne();
serviceOne.execute(typeOne);
Service serviceTwo = new ServiceTwo();
serviceTwo.execute(typeOne);
serviceTwo.execute(typeTwo);
}
}
Expected output:
Service One - Type One!
Service Two - Type One!
Service Two - Type Two!
Tricky question, I may have a solution that could work.
That would be to store the Types, with the code that type does in the form of a HashMap.
HashMap<String, Function<Void, Void>> types = new HashMap<String, Function<Void, Void>>();
Then in the main function, you would fill up the HashMap with the names of the types, and the function it runs.
types.put("Type1",()->{
/*Do something*/
});
types.put("Type2",()->{
/*Do something*/
});
types.put("Type3",()->{
/*Do something*/
});
Then in the Service, you would have an array of Strings for what types it uses. Such as:
String[] serviceTypes = {"Type1", "Type2"};
Finally, in the execute function of the Service you would run the corresponding lambda to the string.
public void execute(String type){
if((new ArrayList<>(Arrays.asList(serviceTypes))).contains(type)) {
Main.types.get(type);
}
}
You might work with an abstract base class.
The base class implements Service and has the execute() method. It does not get around if statements, but after all it could have a list of allowed values, and as soon as the type parameter is contained in the list it would call another method. Per default the method does nothing.
Concise subclasses of the base no longer need to perform the if conditions as they simply override the single methods in the base class. So this works for a whole bunch of quite similar services.
The advantage of this approach is if you have some exotic, incompatible type of service you can skip the if statements by directly overwriting the execute() method. So that pattern is extensible, which is probably worth more than saving a few more if statements.
You can solve this elegantly with the Strategy Design Pattern.
Create a common interface called Strategy
interface Strategy {
void execute(JSONObject payload);
}
Create multiple implementations of Strategy according to your needs:
class ServiceType1 implements Strategy {
//constructors and fields
#Override
public void execute(JSONObject payload) {
//code to be executed for "type1"
}
}
class ServiceType2 implements Strategy {
//constructors and fields
#Override
public void execute(JSONObject payload) {
//code to be executed for "type2"
}
}
...
Group the Service implementations by type, eg.:
Map<String, Strategy> strategyMap = new HashMap<>();
strategyMap.put("type1", new ServiceType1());
strategyMap.put("type2", new ServiceType2());
...
Invoke the desired Service without the need for any if statements, like this:
private static void exec(String payloadType, JSONObject payload) {
strategyMap.get(payloadType).execute(payload);
}
P.S.: if all implementations of Strategy share some common behaviour, you can convert Strategy from interface to abstract class and move the common behaviour there.
wow, your architecture seems much complex. you should consider better hierarchy. but if you can't, why don't you just make a method on Service and let the subtype decide what behavior they want. Then you can call that method from Service to execute
static class Main {
public static void main(String[] args) {
exec(new B());
}
private static void exec(Service service){
service.execute();
}
}
interface Service{
void execute();
}
interface Init{
public void init();
}
interface Action{
public void action();
}
static class A implements Service, Init{
#Override
public void init(){
System.out.println("init a");
}
#Override
public void execute(){
init();
}
}
static class B implements Service, Init, Action{
#Override
public void init(){
System.out.println("init b");
}
#Override
public void action(){
System.out.println("action");
}
#Override
public void execute(){
action();
}
}
What about extracting common logic to the separate class. It cloud be:
BaseService and all other services should implement this one;
ServiceDelegate and all other services should delegate all work to this one.
The below snippet provides the first solution.
// This is you Service interface
public interface Service {
void execute(JSONObject payload, String payloadType);
}
// This is base implementation. Use `Map` to replace `if` statements
public abstract class BaseService implements Service {
private static final Consumer<JSONObject> NULL = jsonObject -> { };
private final Map<String, Consumer<JSONObject>> consumers;
protected BaseService(Map<String, Consumer<JSONObject>> consumers) {
this.consumers = consumers == null || consumers.isEmpty() ? Map.of()
: Collections.unmodifiableMap(consumers);
}
#Override
public final void execute(JSONObject payload, String payloadType) {
consumers.getOrDefault(payloadType, NULL).accept(payload);
}
}
public class ConcreteService extends BaseService {
private static final Consumer<JSONObject> DO_SOMETHING_TYPE1 = jsonObject -> {
// TODO implementation for "type1"
};
private static final Consumer<JSONObject> DO_SOMETHING_TYPE2 = jsonObject -> {
// TODO implementation for "type2"
};
public ConcreteService() {
super(Map.of(
"type1", DO_SOMETHING_TYPE1,
"type2", DO_SOMETHING_TYPE2));
}
}

Best way to store an ordered list of objects that are of different types in Java?

I have several classes that are used to create objects. These objects each have code that must be run that depends on the order of insertion.
They need to be stored in order - and recalled in the order they were stored.
Object A
Object B
Object A
Object A
Object C
Object D
I'm not sure if the proper way of handling this in Java is a generic list and checking typing at runtime.
List<Object> list = new ArrayList<Object>();
I've also thought about storing each object type in their own typed list with a parent object reading from the lists in the proper order. However, this seems more complex than just dealing with checking object types at runtime.
What is the proper "Java" way to handle this?
If the objects do not share a common ancestor:
These classes aren't related. They share no common ancestor.
Then what you can do is to create another class that acts as a wrapper for:
An object of type T.
A Consumer<T> object to act as a reference to the code that needs to be invoked.
For example:
class Invocable<T> {
private final T target;
private final Consumer<T> invocation;
public Invocable(T target, Consumer<T> invocation) {
this.target = target;
this.invocation = invocation;
}
public void runInvocation() {
invocation.accept(target);
}
}
Then create another class that manages a List<Invocable> like the following:
class RunnableList {
private List<Invocable<?>> invocables = new ArrayList<Invocable<?>>();
public <T> void add(T target, Consumer<T> invocation) {
invocables.add(new Invocable<T>(target, invocation));
}
public void run() {
invocables.forEach(Invocable::runInvocation);
}
}
And that's it! Just add ANY object to the RunnableList using the add(T target, Consumer<T> invocation) method and when you are done adding all your objects (with a reference to the respective code to be invoked) just invoke run on the RunnableList.
The following is a full working example of this, try it out to get the idea:
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class RunnableList {
private List<Invocable<?>> invocables = new ArrayList<Invocable<?>>();
public <T> void add(T target, Consumer<T> invocation) {
invocables.add(new Invocable<T>(target, invocation));
}
public void run() {
invocables.forEach(Invocable::runInvocation);
}
static class Invocable<T> {
private final T target;
private final Consumer<T> invocation;
public Invocable(T target, Consumer<T> invocation) {
this.target = target;
this.invocation = invocation;
}
public void runInvocation() {
invocation.accept(target);
}
}
// TEST
public static void main(String[] args) {
RunnableList runnableList = new RunnableList();
runnableList.add(new ClassA(), o -> o.run1("hello from A1"));
runnableList.add(new ClassB(), o -> o.run1("hello from B1"));
runnableList.add(new ClassC(), o -> o.run1("hello from C1"));
runnableList.add(new ClassA(), ClassA::run2);
runnableList.add(new ClassB(), ClassB::run2);
runnableList.add(new ClassC(), ClassC::run2);
runnableList.run();
}
static class ClassA {
public void run1(String msg) {
System.out.println("A.run1: " + msg);
}
public void run2() { System.out.println("A.run2"); }
}
static class ClassB {
public void run1(String msg) {
System.out.println("B.run1: " + msg);
}
public void run2() { System.out.println("B.run2"); }
}
static class ClassC {
public void run1(String msg) {
System.out.println("C.run1: " + msg);
}
public void run2() { System.out.println("C.run2"); }
}
}
Complete code on GitHub
Hope this helps.

Redirect method call at runtime to introduce some kind of sandbox

I'm in bit of a fix with this problem. Hoping for a silver bullet.
I have a few singletons(~10) which all have a few functions (~10 each). My function calls look like this (as they should). Note: Most of these calls are async and do not return anything. Only a handful are synchronous
SingletonClassGorrilla.getInstance().methodSwim(swimmingPool, lifeJacket, whistle);
SingletonClassRacoon.getInstance().methodBark(thief, owner);
I need to put all these calls in a sandbox:
Sandbox.runThisInSandboxMode(new Runnable{
#Override
public void run(){
SingletonClassGorrilla.getInstance().methodSwim(swimmingPool, lifeJacket, whistle);
}
});
As the number of places where they are being called is huge, I am hoping that the sandboxMode can be achieved at the Singleton end.
Possible solution (but infeasible because of the number of functions I will have to wrap like this):
public class SingletonClassGorrilla{
public void methodSwim(WaterBody waterBody, Instrument instrument,
EmResponse emResponse){
Sandbox.runThisInSandboxMode(new Runnable{
#Override
public void run(){
methodSwim(swimmingPool, lifeJacket, whistle, true);
}
});
}
private void methodSwim(WaterBody waterBody, Instrument instrument,
EmResponse emResponse, boolean fromSandbox){
// Do your thang.
}
}
Is there anyway, through use of reflection / annotations / any other thing in the language, which can reduce the amount of changes required?
You can use a Proxy with a suitable InvocationHandler (though you'd have to pull out an interface for each of your singletons). Disclaimer: I haven't tried to actually compile/run this code, but it should give you the general idea. If you care about return values from your singleton, you may have to use Callable instead of/in addition to Runnable in your sandbox interface.
public class SingletonGorilla implements GorillaInterface {
private static SingletonGorilla theRealGorilla;
public static GorillaInterface getInstance() {
//In reality, you'd want to store off the Proxy as well
return Proxy.newProxyInstance(SingletonGorilla.class.getClassLoader(), GorillaInterface.class, new SandboxingHandler());
}
private static class SandboxingHandler implements InvocationHandler () {
public Object invoke(Object proxy, Method method, Object[] args) {
return Sandbox.runInSandbox( new Runnable() {
public void run () {
method.invoke(proxy, args));
}
}
}
}
I'm thinking about something along the following lines:
First, you'll need an interface for each of your singletons:
Interface:
package org.test.proxywrapper;
public interface IGorilla {
public void methodSwim();
}
Implementing class:
package org.test.proxywrapper;
public class Gorilla implements IGorilla{
public void methodSwim()
{
}
}
Then, implement an InvocationHandler that factorize the code that will be common to each call to the methods of Gorilla:
package org.test.proxywrapper;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class WrapperInvocationHandler implements InvocationHandler {
#Override
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
Sandbox.runThisInSandboxMode(new Runnable() {
#Override
public void run() {
Object params = new Object[0];
try {
arg1.invoke(arg0, new Object[]{});
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
});
// return something if you need to
return new Object();
}
}
At this point, in a central place in your application/system, wrap each singleton with a Proxy, and pass the proxy reference around instead of the original wrapped object:
package org.test.proxywrapper;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String argv[])
{
WrapperInvocationHandler wrapperInvocationHandler = new WrapperInvocationHandler();
Class<?>[] implementedTypes = new Class<?>[1];
implementedTypes[0] = IGorilla.class;
IGorilla proxy = (IGorilla) Proxy.newProxyInstance(Main.class.getClassLoader(), implementedTypes, wrapperInvocationHandler);
proxy.methodSwim();
}
}
This simple example compiles and runs as I would expect.
I cut some corners here, skipped the getInstance method, etc, but I guess it gives an idea of how it can be done.

Interfaces - solving ambiguous error

Lets look at the following example:
public class BothPaintAndPrintable implements Paintable,Printable{
public void print() {}
public void paint() {}
}
public interface Paintable {
public void paint();
}
public interface Printable {
public void print();
}
public class ITest {
ArrayList<Printable> printables = new ArrayList<Printable>();
ArrayList<Paintable> paintables = new ArrayList<Paintable>();
public void add(Paintable p) {
paintables.add(p);
}
public void add(Printable p) {
printables.add(p);
}
public static void main(String[] args) {
BothPaintAndPrintable a= new BothPaintAndPrintable();
ITest t=new ITest();
t.add(a);//compiliation error here
}
}
What if I want BothPaintAndPrintable instances to be added to each of the ArrayLists?
One way would be overloading the method with a BothPaintAndPrintable parameter, but I'm trying to see alternatives since doing that might reduce code reuseability. Does anyone have another idea?
You need a third overload:
public <T extends Object&Paintable&Printable> void add(T t) {
paintables.add(t);
printables.add(t);
}
This makes the erasure add(Object), so it doesn't conflict with the other methods, but it does restrict the input to implementors of both Paintable and Printable.
(Guava had to use this trick for Joiner with Iterator and Iterable, because some evil classes out there implemented both, even though it's a terrible idea.)
I would go with a general add(Object o) method, then checking for instanceof, and putting the Object into the according lists.
If the passed Object implements neither interface, throwing an InvalidArgumentException might be a good idea.
Not sure about the best answer as I can't find a way I actually like!
You could use generics, but I don't like either the "instanceof" tests, nor the casts required:
import java.util.ArrayList;
class BothPaintAndPrintable implements Paintable, Printable {
public void print() {
}
public void paint() {
}
}
interface Paintable {
public void paint();
}
interface Printable {
public void print();
}
public class ITest<T> {
ArrayList<Printable> printables = new ArrayList<Printable>();
ArrayList<Paintable> paintables = new ArrayList<Paintable>();
public void add(T p) {
if (p instanceof Paintable) {
paintables.add((Paintable) p);
}
if (p instanceof Printable) {
printables.add((Printable) p);
}
}
public static void main(String[] args) {
BothPaintAndPrintable a = new BothPaintAndPrintable();
ITest<BothPaintAndPrintable> t = new ITest<BothPaintAndPrintable>();
t.add(a);
}
}
Okay I do like the correct answer; however, there is another solution I should point out to the OP.
public static void main(String[] args) {
BothPaintAndPrintable a= new BothPaintAndPrintable();
ITest t=new ITest();
t.add((Paintable)a);
t.add((Printable)a);
}
This works without adding the third member, and even works if you decide to add more interfaces down the road.

Categories