I  know we already discuss that but i still don't understand why  a canonical 
constructor has to be public.

I understand that a canonical constructor is not a simple constructor because 
it is also used as a kind of default de-constructor, but this doesn't work well 
with the current rules for constructors in nested classes/enums and if the 
class is not visible, it's constructor is not visible anyway.

As Brian said in its presentation at Devoxx, records can be used to represent 
local nominal tuples, like

  public void foo() {
    record Pair(String name, int value);
    ...
  }

If one want to add a requireNonNull using a compact constructor, it will be
  public void foo() {
    record Pair(String name, int value) {
      public Pair {
        Objects.requireNonNull(name);
      }
    }
    ...
  }

having to declare the constructor to be public in that case seems weird. 

Mandating that the canonical constructor (hence the compact constructor) to be 
public:
- goes against the idea of encapsulation that a constructor like any members 
should be the least visible
- goes against the rules of default constructors (default constructor use the 
same visibility as their class) [1]
- goes against the rules of constructors in enums (use private or package 
private depending on the kind of enums) [2]

So we a set of rules in the JLS that follows the idea that a constructor should 
not be public by default in nested classes [1] but the rule for a canonical 
constructor doesn't follow the same idea [3], this should be fixed.

In my opinion, the rule for a canonical constructor should be the same as the 
rule for a default constructor.

regards,
RĂ©mi


[1] https://docs.oracle.com/javase/specs/jls/se13/html/jls-8.html#jls-8.8.9
[2] https://docs.oracle.com/javase/specs/jls/se13/html/jls-8.html#jls-8.9.2
[3] 
http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html#jls-8.10.4

Reply via email to