0

I have a collection of classes that implement RaeInterface:

public interface RaeInterface {
    public static String SCHEMA_ID(){return ""; };
}

Each of the implementing classes have a different SCHEMA_ID() defined.

Id' like to pass a class to a method and use the static SCHEMA_ID() method on the class. I can pass the class to a method just fine, but getting at the static SCHEMA_ID() proves frustratingly hard.

public <T extends RaeInterface> void get( Class klass){
   klass.SCHEMA_ID(); // <-- cannot resolve method.
}

Any suggestions on how to resolve this or is this even possible in Java 8?

bart van deenen
  • 434
  • 3
  • 13
  • 2
    probably reflection helps you – Sergii Lagutin Feb 05 '18 at 10:59
  • 2
    https://stackoverflow.com/questions/160970/how-do-i-invoke-a-java-method-when-given-the-method-name-as-a-string – Paolof76 Feb 05 '18 at 11:06
  • 4
    well `Class klass` simply does not have that method, what exactly are you trying to do? You could pass `T t` to that method, but since this is a static method, you do not need an instance at all to invoke it – Eugene Feb 05 '18 at 11:08
  • In java 8 you can have interface with static method. But I don't know if you can override this method in implementations. https://stackoverflow.com/a/513001/3813027 – senerh Feb 05 '18 at 11:10
  • 1
    @senerh they are not inherited, so no, you can't override something that is not inherited – Eugene Feb 05 '18 at 11:11
  • @Eugene Makes sense. – senerh Feb 05 '18 at 11:12
  • 5
    Unless I'm misunderstanding something, if _"each of the implementing classes have a different SCHEMA_ID() defined"_, why is this a static method ? Can't you just have a default implementation in this interface and then override id per your need in the corresponding implementing classes and let polymorphism do its job? – Alexis C. Feb 05 '18 at 11:16
  • 3
    @senerh, you can't override them. Overriding of methods refers to a mechanism fo `invokevirtual` instruction, where an exact binding to the method is determined by inspecting the object which is passed as a first (hidden) argument to method invokation. Static methods are called with `invokestatic` instruction, there is no hidden argument to inspect, and exact binding to method is determined at compile time. – M. Prokhorov Feb 05 '18 at 11:26
  • 1
    If a class implementing your interface also has a `schemaId` method (please follow coding conventions), then it’s not the same method, so it makes no difference whether such a method exists in the interface or not. I think you want an instance method (non-static method) so you can pass an instance to the method rather than its class. – Ole V.V. Feb 05 '18 at 11:34
  • Thank you all for thinking along! I had a lot of classes generated from Avro files, where I used some sed trickery to include a static method SCHEMA_ID() in every class that returned a string identifying the original Avro schema. What I tried to do with the `RaeInterface` was to provide a nice clean typesafe way to get at that SCHEMA_ID function, for every class (not instance!) that I knew to be one of my generated java files. I ended up going with reflection, much though I dislike it. – bart van deenen Feb 06 '18 at 14:06

2 Answers2

2

Static methods cannot override in implementation of the Interface. If you want to override use default methods in interface.

Interface :

     public interface RaeInterface {
        default String SCHEMA_ID() {
          return "";
        }
      }

Your mention method :

        public <T extends RaeInterface> void get(T klass) {
          klass.SCHEMA_ID();
        }

Implement class :

      class B implements RaeInterface {
        @Override
        public String SCHEMA_ID() {

          return "B";//the ID
        }
      }

      class C implements RaeInterface {
        @Override
        public String SCHEMA_ID() {

          return "C";//the ID
        }
      }
janith1024
  • 1,062
  • 3
  • 12
  • 21
  • `Static methods cannot override in implementation of the Interface` while this is correct, the better one is that they are not inherited at all (if it were a class it would be inherited, but not overridable) – Eugene Feb 05 '18 at 12:44
  • 2
    @Eugene And it makes sense to not inherit static methods, as they belong exclusively to the class and not to the instance. Letting classes' static methods be inherited by subclasses was a design error IMO. – fps Feb 05 '18 at 13:10
  • 1
    @FedericoPeraltaSchaffner may be, you might be right here since this is allowed `Test t = null; t.someStaticMethod`, but this will fail `t::someStaticMethod` – Eugene Feb 05 '18 at 13:21
  • 1
    @Eugene being able to call `static` methods through object instances is *the other* design mistake, additionally to inheriting `static` methods. – Holger Feb 05 '18 at 14:18
2

I think you want an instance method in your interface:

public String schemaId();

Each implementing class can (and must if not abstract) implement this method. It doesn’t need to use any instance stuff for the implementation.

Your calling method gets much simpler and doesn’t need any generics:

public void get(RaeInterface instance){
    instance.schemaId();
}

For inspiration you may look at how the java.util.Comparator interface is used. Usually classes implementing this interface don’t contain any instance variables, so you would think the compare method could just as well be static. Its probably only non-static to allow different implementations.

If you really insist on a static method, Sergey Lagutin is correct that reflection will solve your problem. But again, it’s getting more complicated and I don’t see why you should want such a solution.

Ole V.V.
  • 65,573
  • 11
  • 96
  • 117