New features of jdk10: VAR generics and multiple interface implementations
brief introduction
In the new feature of jdk10: local variable type VaR, we talked about why and how to use var.
Today, let's take a deep look at VaR and generics, multiple interface implementations.
Implement multiple interfaces
In the implementation of JDK and our daily work, we often need to implement multiple interfaces. We give two common examples: ArrayList and copyonwritearraylist. Let's look at their definition first:
public class ArrayList<E> extends AbstractList<E>
implements List<E>,RandomAccess,Cloneable,java.io.Serializable
public class CopyOnWriteArrayList<E>
implements List<E>,java.io.Serializable
We can see that both ArrayList and copyonwritearraylist implement four interfaces: list, randomaccess, Cloneable and serializable.
If we have an ArrayList creator that can create one of ArrayList or copyonwritearraylist, how should the code be written?
public Object createList(boolean flag){
if(flag){
return new ArrayList<>();
}else{
return new CopyOnWriteArrayList<>();
}
}
Because the returned value may be ArrayList or copyonwritearraylist, we can only replace the object to be returned with object.
If you return an object, you won't have the advantage of generics. Is there any way to let us know exactly what type of object to return?
Your first thought may be to create a new interface, inherit list, Java io. Serializable, and then createlist returns the newly created interface.
public interface ListInterface<E> extends List<E>,java.io.Serializable {
}
Then rewrite the createlist method:
public <E> ListInterface<E> createListWithInterface(boolean flag){
if(flag){
return (ListInterface<E>) new ArrayList<E>();
}else{
return (ListInterface<E>) new CopyOnWriteArrayList<E>();
}
}
The new method can be generic and clearly indicates that what to return is a listinterface.
There is no problem using the newly generated listinterface in your own code. Consider that if your code is referenced by others or used as a public library, the third party may not know what your newly created listinterface does.
Can we use a more intuitive way to create lists? Of course, the answer is yes. Take the following example:
public <T extends List<E> & RandomAccess & Cloneable & java.io.Serializable,E> T createListWithInterfaceT(boolean flag){
if(flag){
return (T) new ArrayList<E>();
}else{
return (T) new CopyOnWriteArrayList<E>();
}
}
In the above example, we use generic T and inherit four interfaces at the same time. Then convert the created list to t return.
In this way, we can get the public types of ArrayList and copyonwritearraylist without creating a new interface.
Use multiple interfaces
Above, we created a generic t that implements multiple interfaces. So what if you want to use it?
public <T extends List<E> & RandomAccess & Cloneable & java.io.Serializable,E> void useGenericityType(){
VarGenericity varGenericity=new VarGenericity();
T list=varGenericity.createListWithInterfaceT(true);
}
In order to use t inside a method, we must restate the definition of T above the method definition.
Although this can realize our functions, it is too troublesome.
Use VaR
At this time, you can use VaR variable instead. Let's see the following example:
public void useVarInGenericityType(){
VarGenericity varGenericity=new VarGenericity();
var list=varGenericity.createListWithInterfaceT(true);
}
Is it simple, and the VaR list variable retains all the public methods of the four interfaces.