In Java generics you can use "&" to specify multiple interfaces as type bounds for a type parameter. This allows us for example to manipulate objects of different types with common interfaces to be manipulated uniformly even if there is not an parent interface for those common ones. My question is, how can this be used? For What purposes? I can imagine using this feature for collections, but how is it really than creating a new interface? This cannot be used dynamically, nor for type parameters. Is it just a syntactic sugar, or is there real use case for this feature?
There are use cases for this, but there are generally alternate ways to achieve the same results. This is just another tool in the toolbox available for Java developers.
But let's say you have a JPanel
that takes a custom JComponent
that implements MyInterface
. It can be one of several components, depending on another option selected on the panel. You want to reference this as a JComponent
so that you can interact with it and place it, yet you also need to reference it as MyInterface
to call some custom methods.
In this case, you cannot simply add the JComponent methods you need to MyInterface
, because you have to call JPanel.add(component
to put it on the overall panel. You can't make your interface somehow extend JComponent
because Java doesn't work like that. You cannot create a custom extentsion to JComponent
, because perhaps sometimes your object is another panel, sometimes it's a text field, and you don't want to restrict yourself. So you would reference it as a JComponent & MyInterface
.
Here is an example taken from my Java Generics book:
public static <S extends Readable & Closeable,
T extends Appendable & Closeable>
void copy(S source , T target, int size){
//code to copy from source to target
}
The method above takes any source that implements both Readable
and Closeable
and any target that implements both Appendable
and Closeable
and copies from source to target. You might wonder why we can't simplify it to:
public static void copy(Reader source, Writer target, int size)
This will indeed admit most of the same classes but not all of them. For instance,
PrintStream
implements bothAppendable
andCloseable
, but is not a subclass ofWriter
. Furthermore, you can't rule out the possibility that some programmer using your code might have his or her own custom class that, say, implementsReadable
andCloseable
but is not a subclass ofReader
.
I was thinking, that an interresting use case might be using it in combination with multiple inheritance (composition and delegation), especially with generalization sets to create stronger constraints. For example in use case modeling, an actor might be an organization, system or subsystem, but at the same time also primary, secondary and ternary actor. All of these might require different behaviour (e.g. ternary actor has interrests, but primary has goals), so they cannot be collapsed. Now to work with a bank, which might be Ternary actor as well as organization, you would use this feature.