2

When running this:

import java.util.Arrays;

public class TestA {
    public static void main(String[] args) {
        System.out.println(Arrays.toString(TestB.class.getConstructors()));
    }
}

class TestB extends TestA {

}

The result will be

[]

When calling the default constructor using reflection, the code will crash with NoMethodFoundException: TestB.<init>(). So somehow the JVM doesn't know that there is a default constructor. BUT when you simple call new TestB(), everything is fine (as it should be).

Adding to that, when I decompile the .class files, both classes have a default constructor.

What's going on under the hood or what am I missing?

Nighley
  • 31
  • 2
  • Question got improperly reopened by [sp00m](https://stackoverflow.com/users/1225328/sp00m), so I'll repeat the correct duplicate here in the comment: [getConstructor with no parameters](//stackoverflow.com/q/27579783) – Tom Jul 08 '21 at 13:45
  • @Tom I'm not sure I agree, the question you're linking has an explicitly declared constructor with "package visibility", this one has no constructors declared at all (explicit vs implicit). – sp00m Jul 08 '21 at 13:48
  • @Tom EDIT: sorry, it must end up being the same case indeed, I thought default constructors were always public, my bad. – sp00m Jul 08 '21 at 13:51
  • 1
    @sp00m Its not that important what the linked question has or hasn't, important is the answer, and this explains the issue here, like the second answer here. – Tom Jul 08 '21 at 13:51
  • 1
    @Tom I disagree with the duplicate. To be able to answer the question, you would also need to know about the visibility of default constructors, and combine that with how `getConstructors` work. – Sweeper Jul 08 '21 at 13:56
  • @Sweeper Well, good for us that this is what the accepted answer of the linked question does. It explains what `getConstructors()` does, like your answer, it explains that the visibility of the class affects the default constructor, like your answer, and it references the same JLS rule regarding the default constructor, like your answer. But yes, this question is _obviously_ not a duplicate. – Tom Jul 08 '21 at 14:10

1 Answers1

3

getConstructors:

Returns an array containing Constructor objects reflecting all the public constructors of the class represented by this Class object.

The constructor of TestB is not public! According to JLS §8.8.9:

If a class contains no constructor declarations, then a default constructor is implicitly declared. The form of the default constructor for a top level class, member class, or local class is as follows:

  • The default constructor has the same accessibility as the class.
  • ...

TestB has the "package" access level (no access modifiers), so the default constructor has that access level too. Therefore, getConstructors doesn't include it in its returned array. It turns out this has nothing to do with TestB being a subclass of TestA.

If you want to get it, use getDeclaredConstructors.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Oh, TIL! My bad, I didn't know the default constructor takes the visibility of the class. – sp00m Jul 08 '21 at 13:49