How to find the default method from an interface using java reflection?

I want to find if the method is the "default method via java reflection.I tried to print java.lang.Iterable methods.


Code snippet:

 import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class ReflectionTest { public static void main(String[] args) { Class c = Iterable.class; for(Method m : c.getDeclaredMethods()) { System.out.print(Modifier.toString(m.getModifiers())); System.out.println(" "+m.getName()); } } } 


Result:

 public abstract iterator public spliterator public forEach 

here, spliterator () and forEach () should be printed by default .
Please correct me if my interpretation is incorrect.

+5
source share
2 answers

Do not rely on Modifier.toString in this way. In the past, modifiers for classes, fields, and methods received unique values, so you could interpret them without looking at the type of object that has a modifier, as this method suggests.

But while Java evolved, more modifier bits were added, and it was not possible to save this property. In particular, when passing the modifier bits of the Modifier.toString method unmodified, you will get the following amazing behavior:

  • the bridge method will be printed as volatile
  • varargs method will be printed as transient

Therefore, you must filter out the bit. Java 7 introduced a method that provides the correct mask so you can use Modifier.toString(m.getModifiers()&Modifier.methodModifiers()) .

But this only works because the old Java keywords are mapped to unique modifier bits, and the new modifier bits are not associated with keywords. With newer versions of Java, even this may not be enough.

For the default keyword, this is even simpler: there is no modifier bit associated with the keyword. If the public , non abstract , non static method appears in the interface , it must be the default method. How Method.isDefault() determines whether a method is a default method. Modifier.toString(…) has no way of knowing if the declaration class is interface and therefore will never print default .

+5
source

In recent versions of java8 updates, we have isDefault() in the java.lang.reflect.Method class, which does the trick.
Changing my previous code gives a little result.

The code:

 import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class ReflectionTest { public static void main(String[] args) { Class c = Iterable.class; for(Method m : c.getDeclaredMethods()) { System.out.print(Modifier.toString(m.getModifiers())); System.out.println(" "+(m.isDefault()?"default ":"")+m.getName()); } } } 


Conclusion:

 public abstract iterator public default spliterator public default forEach 


Note: I tested this in jdk8 20 update

+4
source

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


All Articles