One standard solution that should be avoided if / else-chains in such situations is to force classes to implement some interface that contains a method that makes objects know what to do themselves - for example, use inheritance, as you suggest.
Concrete classes know their specific types, how to copy themselves, etc., but you donβt know what is in the loop - so it makes sense to shift the responsibility for creating new concrete classes directly to specific classes.
What I would do is add a new method to the Y interface, which creates a new instance. For example, if you just want to take a copy of the instances in the list, you can add βcopyβ factory -method to Y :
public interface Y { ... public Y copy(); ... }
Each implementation of Y must implement a copy method. He knows how to copy himself. Example:
public class MyClass implements Y { ... public MyClass copy() { return new MyClass(...); } ... }
Thus, creating new instances when repeated in the list then simply becomes something like this:
List<Y> ys = ...get list from somewhere...; for (Y y : ys) { Y copy = y.copy(); ... }
Please note that there is no reflection or other hacks needed for this approach.
Also note that the loop should not know anything about specific classes - it should only know the Y interface. All code specific to specific classes is stored inside the classes themselves. This simplifies code usage (avoids instanceof + if / else chains).
Instead of the copy method, you could of course also create more complex methods, perhaps by taking some parameters. This can be useful if the objects do not just need to copy themselves, but must themselves create a new instance in some special way based on some input.
(Note: This copy method may remind you of a βclone,β but since Java cloning is severely broken, this is usually the best approach).
Note. I assumed that both wrappers Ai' and Ai extend Y
Note. If you cannot make changes to Y , but you can change adapter classes, you can create a new interface Y' that extends Y and which adapter classes implement it, and use List<Y'> instead of List<Y> , which you iterate over channels.