Almost Useful: Java Type Intersection.
First, for my subscribers that celebrate it, Happy Thanksgiving!
I’ve written about it before, but I think its worth revisiting. Type intersection would be a highly useful feature if not for one thing. “It is not possible to write an intersection type directly as part of a program; no syntax supports this.” - JLS (ยง4.9). That seems like a poor excuse to not support a feature as potentially powerful as type intersection could have been.
They were bold enough to add syntax all over the place for Generics. They added new syntatical meanings for ‘?’ ‘<’, and ‘>’. As a matter of fact, they added a syntax within that construct for handling Type Intersections. Would it really be that difficult to reuse that syntax outside of capture conversions and type inference? Heck, maybe even make it reifiable, although that’s not *as* important.
One example others have used in the past where it would be useful to have this type intersection is with the marker interface RandomAccess. While marker interfaces are less useful now that we have annotations, it none-the-less exists, and can be useful for ensuring that the user of an algorithm passes in a compatible list.
For example, its quite possible to do the following, even with the currently crippled implementation of type intersection.
<T extends List<String> & RandomAccess> void foo(T list) { ... }
You know that you’re getting a random access list. The pain point is that you can not do the following:
<T extends List<String> & RandomAccess> T foo() { return new ArrayList<String>(); }
The reason that isn’t legal is quite simple, even if its not obvious. T is any type that satisfies List<String>&RandomAccess, so you don’t know that it is an ArrayList. You might have MyNonArrayList<String> list = foo(); Oops, that would be an incompatible assignment.
The better approach would be to have the return type be an explicit type that is List<String>&RandomAccess. As a matter of fact, my suggestion is to use that syntax exactly, unless there is a compiler-grammar reason not to. So, our T foo() line becomes:
List<String>&RandomAccess foo() { return new ArrayList<String>(); }
So then we can do: List<String>&RandomAccess list = foo(); Actually, we could just use List<String> list=foo() if we don’t care about RandomAccess.
An important addition to make to this would be casting. For legacy support, if I have a List<String>, but I know that it should be an ArrayList (or some other RandomAccess), I should be able to cast: foo((List<String>&RandomAccess)list);
Tags: Java, missing features, type intersection

November 23rd, 2007 at 3:33 pm
[…] becomes even more useful if we combine the concept with the fully useful Type Intersection (Not yet implemented). If both of these features were implemented, then you could write something […]
December 10th, 2007 at 5:36 am
I’m sorry, you’ll have to explain it again. Why can’t you return “new ArrayList<String>()”? I mean, I tried it myself and saw it doesn’t work, but I still don’t get it. ArrayList DOES apply to the group of types that are both List AND RandomAccess… So why?
December 10th, 2007 at 9:24 am
<T extends List<?> & RandomAccess> T foo()has a return of type T, not ArrayList. A caller is able to specify the type of T, which might not be ArrayListArrayList is not a subclass of SomeRandomAccessListType, so you would get a cast error.
December 11th, 2007 at 5:06 am
Ah, I see now. I suppose I got confused as usually my return types are ? extends Something, which would allow this.
December 11th, 2007 at 9:54 am
You cant have a ? return type, can you?
December 12th, 2007 at 3:12 am
Daniel, note that current Java do not allows for direct use of intersection types as part of the program. However, you can always use a wildcard type as a reference holder of any intersection type instance you wish.
For example, having a reference holder declared as:
public class ListRef<T extends List & RandomAccess> { public final T value; public ListRef(T value) { this.value = value; } }you can return any implementation matching declared intersection type this way:
public ListRef foo() { return new ListRef<ArrayList>(new ArrayList()); }and use it as follows:
I think, it is a bit more than just “Almost Useful” Java feature, isn’t it?
December 12th, 2007 at 11:09 am
Hmm, thats interesting, but it is still a hack that shouldn’t have to be. Anyway, I think I would have this:
public class RandomAccessListDelegate<E, T extends <List<E> & RandomAccess> implements RandomAccess, List<E> { private final T delegate; private RandomAccessListDelegate(T delegate) { this.delegate = delegate; } public static <E, T extends <List<E> & RandomAccess> RandomAccessListDelegate<E, T> create(T delegate) { return new RandomAccessListDelegate(delegate);
}
public T getDelegate() { return delegate; }
// Delegate all methods to delegate
// [code snipped]
}
Still, I shouldn’t have to jump this hoop.
December 12th, 2007 at 12:10 pm
Yes, we shouldn’t have to do that. However, we can!
The reason intersection types are not implemented for direct use is in the way the JVM works, and Java 5 is chosen to be implemented. Currently, there is no special runtime type to represent intersection type, it’s always compiled as the erasure of its first bound.
Implementing it in a different way most probably requires some changes in the JVM and/or generation of synthetic classes. From a number of reasons it was a change the Java architects wanted to avoid. But, who knows? Maybe future versions will support that?…
P.S. Thank you for formatting my previous comment, but there are still some incompleteness in my code caused by a replay form.
In my original example a reference holder was declared as:
public class ListRef<T extends List<String> & RandomAccess> { public final T value; public ListRef(T value) { this.value = value; } }Example method implementation as:
public ListRef<?> foo() { return new ListRef<ArrayList<String>>(new ArrayList<String>()); }And sample use snippet as: