JDK 16 RFR of JDK-8071961: Add javac lint warning when a default constructor is created

Jan Lahoda jan.lahoda at oracle.com
Thu Jul 30 10:27:26 UTC 2020


Hi Joe,

Thanks for this addition! A few comments for your consideration:
-the logic in checkDefaultConstructor could probably be simplified - 
going from "c" the symbol, and as long as the symbol being check is a 
TYP and PUBLIC, go to its owner. E.g. like:
         if (lint.isEnabled(Lint.LintCategory.DEFAULT_CTOR) &&
             Feature.MODULES.allowedInSource(source)) {
             Symbol test = c;
             while (test.kind == TYP && (test.flags() & PUBLIC) != 0) {
                 test = test.owner;
             }
             if (test.kind != PCK) {
                 return ;
             }

-not sure if the check for unnamed package is needed, but it would be 
nice to have a test verifying proper behavior for unnamed packages, 
unnamed module and in non-module mode (i.e. JDK 8 mode).

-should the warning be suppressable? We would need to defer the warning 
using deferredLintHandler and check if it was already suppressed.

-should protected classes (classes with effectively protected access) be 
covered as well?

-for tests like this, I would suggest to consider using TestRunner, 
ModuleTestBase or another framework we use for programmatic tests, to 
avoid adding many small files for testcases, but I don't mind those too 
much. See e.g.:
test/langtools/tools/javac/options/BCPOrSystemNotSpecified.java

Jan

On 29. 07. 20 22:10, Joe Darcy wrote:
> Hello,
> 
> Please review the code changes and CSR for
> 
>      JDK-8071961: Add javac lint warning when a default constructor is 
> created
>      webrev: http://cr.openjdk.java.net/~darcy/8071961.5/
>      CSR: https://bugs.openjdk.java.net/browse/JDK-8250795
> 
> Some background on the design of the warning and broader usage context, 
> while default constructors can be convenient for informal code, they can 
> be a bit troublesome for more formal APIs, such as the public classes of 
> packages in the JDK. One issue is that default constructors do not have 
> javadoc. Another is that a class that semantically should not be 
> instantiated, say it is a solely a holder for  static constants and 
> methods, can get instantiated and subclassed. (Subclasssing such a class 
> is an anti-pattern to allow use short names for the static members, 
> which is no longer necessary since static imports as of Java SE 5.0.)
> 
> Until they were recently fixed, there were about one hundred remaining 
> default constructors in the JDK API outside of the client libraries ( 
> JDK-8250212 Address reliance on default constructors in the JDK 
> (umbrella) ). Other occurrences of this issue were sporadically fixed 
> over the years ( JDK-8236695, JDK-8177153, JDK-8071959, etc.).
> 
> In terms of detailed criteria to issue the new warnings, there was the 
> usual tension in warnings between reducing false positives and false 
> negatives. For example, warning for *any* default constructor, even in a 
> throw-away class, would be more annoying than helpful. With some 
> guidance from the JDK code base, criteria in the current patch are a 
> default constructor merits a warning if:
> 
> * The class is in a named package and the packaged has an unqualified 
> export from its module AND
> * The class is public and, if it is a nested class, all of its lexically 
> enclosing types are public too.
> 
> An unqualified export, where the package is available to use to any 
> module and not just named ones, was taken to indicate classes in the 
> package can comprise a "formal API". It would be simple to change this 
> to an unqualified export, but I wanted to avoid unwanted instances of a 
> new warning. If a public nested class is a non-public enclosing class, 
> the nested class is not directly part of the exported API. These 
> combinations of kinds of exports and nesting are tested in the tests in 
> the DefaultCtor directory.
> 
> The text of the warning message implies what criteria are being used:
> 
>   # 0: symbol, 1: symbol, 2: symbol
>   compiler.warn.default-ctor=\
>       class {0} in exported package {1} of module {2} relies on a 
> default (implicit) constructor
> 
> Once the javac-related changes are reviewed, I'll send a RFR out to 
> build-dev for the make system updates. Basically modules whose use of 
> default constructors has not been addressed (java.desktop, 
> jdk.accessibility, jdk.unsupported.desktop, etc.) have the new warning 
> disabled.
> 
> Thanks,
> 
> -Joe
> 


More information about the compiler-dev mailing list