As of Java 8 you can have default or static methods implemented in Interfaces as the below
public interface DbValuesEnumIface<ID, T extends Enum<T>> {
T fromId(ID id);
ID getId();
static String getDescriptionKey(){
return "this is a test";
}
}
I would like to declare the above with the static method having a signature that uses bounds defined by the implementing classes since the method's implementation should be the same for all,with the only thing different should be the generics declared, as such:
public interface DbValuesEnumIface<ID, T extends Enum<T>> {
public static T fromId(ID id) {
if (id == null) {
return null;
}
for (T en : T.values()) {
if (en.getId().equals(id)) {
return en;
}
}
}
ID getId();
String getDescriptionKey();
}
...
public enum Statuses implements DbValuesEnumIface<Integer,Statuses>
which breaks because T and ID are not static and cant be referenced from a static context.
So, how should the above be modified to compile successfully and if thats not possible, how the above should be implemented to achieve the desired purpose while avoiding code duplication within implementing classes .
Static and non-static generic methods are allowed, as well as generic class constructors. The syntax for a generic method includes a list of type parameters, inside angle brackets, which appears before the method's return type.
Similar to Default Method in Interface, the static method in an interface can be defined in the interface, but cannot be overridden in Implementation Classes. To use a static method, Interface name should be instantiated with it, as it is a part of the Interface only.
This is because it's not allowed in java, since Object is the base class for all the classes and we can't have one class level static method and another instance method with same signature.
Static method definition. The first line of a static method definition, known as the signature, gives a name to the method and to each parameter variable. It also specifies the type of each parameter variable and the return type of the method. Following the signature is the body of the method, enclosed in curly braces.
Since there is no relationship between static
methods and the class’ type parameters, which describe how instances are parameterized, you have to make the static
method generic on its own. The tricky part is to get the declarations right to describe all needed constraints. And as this answer already explained, you need to a a Class
parameter, as otherwise, the implementation has no chance to get hands on the actual type arguments:
public interface DbValuesEnumIface<ID, T extends Enum<T>> {
public static
<ID, T extends Enum<T>&DbValuesEnumIface<ID,T>> T fromId(ID id, Class<T> type) {
if (id == null) {
return null;
}
for (T en : type.getEnumConstants()) {
if (en.getId().equals(id)) {
return en;
}
}
throw new NoSuchElementException();
}
ID getId();
String getDescriptionKey();
}
Note that the type parameters of the static
method are independent from the class’ type parameter. You may consider giving them different names for clarity.
So now, given you enum Statuses implements DbValuesEnumIface<Integer,Statuses>
example, you can use the method like Statuses status = DbValuesEnumIface.fromId(42, Statuses.class);
Note that for default
methods, it is possible to access the actual type, as a method providing the enum
type will be provided by the implementation. You only have to declare the presence of the method within the interface
:
public interface DbValuesEnumIface<ID, T extends Enum<T>&DbValuesEnumIface<ID,T>> {
public default T fromId(ID id) {
if (id == null) {
return null;
}
for (T en : getDeclaringClass().getEnumConstants()) {
if (en.getId().equals(id)) {
return en;
}
}
throw new NoSuchElementException();
}
Class<T> getDeclaringClass();//no needed to implement it, inherited by java.lang.Enum
ID getId();
String getDescriptionKey();
}
However, the obvious disadvantage is that you need a target instance to invoke the method, i.e. Statuses status = Statuses.SOME_CONSTANT.fromId(42);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With