Static method in a shared signature interface

With Java 8, you can use standard or static methods in interfaces, as shown 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 above when the static method has a signature that uses the boundaries defined by the implementation classes, since the implementation of the method should be the same for everyone, with the only difference being the declared generics:

 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 is interrupted because T and ID are not static and cannot refer to a static context.

So, how it should be changed for compilation, and if it is impossible, then how it should be implemented to achieve the desired goal, avoiding duplication of code within the implementation classes.

+5
source share
3 answers

Since there is no relationship between static methods and class type parameters that describes how instances are parameterized, you must make the general static method common. The hard part is to get declarations to describe all the necessary restrictions. And since this answer has already been explained, you need to specify the aa Class parameter, since otherwise the implementation has no chance to get real arguments like:

 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 parameters of the static method type are independent of the class type parameter. You might consider giving them different names for clarity.

So, given the example enum Statuses implements DbValuesEnumIface<Integer,Statuses> , you can use a method like Statuses status = DbValuesEnumIface.fromId(42, Statuses.class);


Note that for default methods, you can access the actual type, since the method providing the enum type will be provided by the implementation. You only need to declare a method in 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 drawback is that you need the target instance to call the method, i.e. Statuses status = Statuses.SOME_CONSTANT.fromId(42);

+4
source

There is no easy way, as far as I can tell, first you need to change your method to default , you can read here why you can 'Use generics in a static context.

But even if you change it to default , it still won’t work, since you need to pass an instance or type of an enumeration class to this method, something like this:

 public default T fromId(ID id, Class<T> t) { if (id == null) { return null; } for (T en : t.getEnumConstants()) { // dome something } return null; } 

Now you are facing another problem, inside fromId - the only thing you know is that T extends enum - it can't be your enum, so getId (which seems like you have enums) is simply not known to the compiler.

I don’t know an easy way to make this work apart from declaring an interface, for example:

 interface IID { public int getId(); } 

so that your enum implements it:

 static enum My implements IID { A { @Override public int getId() { // TODO Auto-generated method stub return 0; } }; } 

and change the declaration to:

 public interface DbValuesEnumIface<ID, T extends Enum<My> & IID> 
+2
source

You can go from static to default and successfully compile it.

default EvaluationStatuses fromId(Integer id)

+1
source

Source: https://habr.com/ru/post/1273566/


All Articles