3

The following code:

Class.forName("java.lang.String")
     .getDeclaredMethods
     .find(_.getName == "join")
     .get
     .getModifiers & ~(java.lang.reflect.Modifier.methodModifiers())

Evaluates to 128. It seems to me that it should evaluate to 0, because every modifier that's attached to the java.lang.String#join method should be within the set of java.lang.reflect.Modifier.methodModifiers().

Looking at the constants in java.lang.reflect.Modifier, it seems that 128 corresponds to the modifier bit java.lang.reflect.Modifier.TRANSIENT. How can a method end up being flagged as transient?

Vince
  • 14,470
  • 7
  • 39
  • 84
Li Haoyi
  • 15,330
  • 17
  • 80
  • 137
  • 3
    Just as a hint, for questions like this, I'd try to reproduce in plain Java first - I strongly suspect you'll get the same result, and then that's eliminated Scala from the problem *and* made the question more amenable to "just Java" developers. – Jon Skeet Sep 07 '17 at 07:47
  • The constants within `java.lang.reflect.Modifier` stem from a time when all bits where unambiguous, regardless of whether you are looking at the modifiers of a field, method or class. Since Java 5, this is not the case anymore and the new modifier bit have not been added to that class. – Holger Sep 07 '17 at 13:15
  • TIL. But I'd have preferred an Ammonite screenshot. – som-snytt Sep 07 '17 at 16:43

1 Answers1

3

Brief Explanation

There are two flags with the value 0x80 (128), VARARGS and TRANSIENT, as per the answer here, so the method is actually a varargs method.

The JavaDoc confirm that this method is varargs, so the flag makes sense

Worked example

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

class TestClass {
  public static void main(final String... args) throws Throwable{
    int methodModifiers = Class.forName("java.lang.String")
        .getDeclaredMethod("join", CharSequence.class, CharSequence[].class)
        .getModifiers();

    Field varargsField = Class.forName("java.lang.reflect.Modifier")
        .getDeclaredField("VARARGS");
    varargsField.setAccessible(true);

    int varargsF = varargsField.getInt(null);
    int staticF = Modifier.STATIC;
    int publicF = Modifier.PUBLIC;

    if (methodModifiers == publicF + staticF + varargsF) {
      System.out.println("Correct");
    } else {
      System.out.println("Wrong");
    }
  }
}
jrtapsell
  • 6,719
  • 1
  • 26
  • 49
  • Javadoc for `Modifier` excludes (omits) the table in section 4.6 of the jvm spec for methods. It would be less confusing if they were explicit about what they intended. Comparing 4.5 and 4.6, volatile and bridge are also overloaded. – som-snytt Sep 07 '17 at 16:42