Repository navigation
"Classes and Objects" tutorial (https://dev.java/learn/classes-objects/ ) discussion of access modifiers should probably be updated for changes with Java Platform Module System released in Java 9 (in 2017) #211
Description
Hello dev.java team!
Thanks again for all these wonderful articles.
It seems though there are excellent separate articles within dev.java on the impacts of the Java Platform Module System (JPMS; since Java 9 in 2017, https://openjdk.org/projects/jigsaw/spec/ ) when used for a project on access,
the "Classes and Objects" tutorial https://dev.java/learn/classes-objects/ has not yet been updated for the impact of modules on access. Also, that reflection can bypass access controls under some circumstances might be mentioned in passing (could link to e.g. https://dev.java/learn/reflection/fields/#accessible (archived as is at: https://web.archive.org/web/20260317205612/https://dev.java/learn/reflection/fields/#accessible )).
Regarding https://dev.java/learn/classes-objects/creating-classes/ (archived as is at https://web.archive.org/web/20260317200949/https://dev.java/learn/classes-objects/creating-classes/ ):
- Re: "public modifier—the field is accessible from all classes." it seems this should be updated to account for the Java Platform Module System which, when used, only reveals to code outside the module the public modified items in packages exported by the module (or opened, if considering reflective access) (exports or opens can also be qualified to restrict such access only to other particular target modules).
[dev.java already has other articles on the impact of JPMS on access at https://dev.java/learn/modules/intro/ (archived as is at: https://web.archive.org/web/20260317203840/https://dev.java/learn/modules/intro/ ),
and https://dev.java/learn/modules/qualified-exports-opens/ (archived as is at: https://web.archive.org/web/20260317204235/https://dev.java/learn/modules/qualified-exports-opens/ ), and https://dev.java/learn/modules/opening-for-reflection/ (archived as is at: https://web.archive.org/web/20260317204550/https://dev.java/learn/modules/opening-for-reflection/ ).
See also:
https://docs.oracle.com/javase/specs/jls/se25/jls25.pdf
Example 6.6-2. Access to public Fields, Methods, and Constructors
A public class member or constructor is accessible throughout the package where it is
declared and from any other package, provided the package in which it is declared is
observable (§7.4.3).
Where §7.4.3 is 7.4.3 Package Observability and Visibility,
which states:
A package is visible to a module M if and only if an ordinary compilation unit
containing a declaration of the package is visible to M
[...]
A package is uniquely visible to a module M if and only if one of the following holds:
• An ordinary compilation unit associated with M contains a declaration of the
package, and M does not read any other module that exports the package to M.
• No ordinary compilation unit associated with M contains a declaration of the
package, and M reads exactly one other module that exports the package to M.
and re: classes the JLS 25 in 6.6.1 says
If a top level class or interface (§7.6) is declared public and is a member of a
package that is exported by a module, then the class or interface may be accessed
by any code in the same module, and by any code in another module to which
the package is exported, provided that the compilation unit in which the class or
interface is declared is visible to that other module (§7.3).
• If a top level class or interface is declared public and is a member of a package
that is not exported by a module, then the class or interface may be accessed by
any code in the same module [me: including the unnamed module].
]
- Re: "private modifier—the field is accessible only within its own class" might also be updated to mention reflective access can work around this under certain conditions (see https://dev.java/learn/reflection/fields/#accessible (archived as is at: https://web.archive.org/web/20260317205612/https://dev.java/learn/reflection/fields/#accessible ) (relevant: section was added in discussion at Tiny typos in Date Time articles ( https://dev.java/learn/date-time/ ) and Reflection articles ( https://dev.java/learn/reflection ) #191 (comment) ).
In https://dev.java/learn/classes-objects/more-on-classes/#controlling-access (archived as is at: https://web.archive.org/web/20260317203241/https://dev.java/learn/classes-objects/more-on-classes/#controlling-access )
Re: the table shown for "Controlling Access to Members of a Class", quoted below:
The following table shows the access to members permitted by each modifier.
Modifier Class Package Subclass World
public Y Y Y Y [should be updated for JPMS post Java 9, for projects using JPMS]
protected Y Y Y N
no modifier Y Y N N
private Y N N N
This "Controlling Access to Members of a Class" table should also probably be updated for the release of the Java Platform Module System (JPMS) in Java 9, which, when a project uses JPMS, restricts access to even public types and members by code outside the module based on which packages are exported by the module (or opened, concerning reflective access) (and exports or opens can be qualified to restrict such access only to other particular target modules).
[again, for ease of reference, dev.java already has other articles on the impact of JPMS on access at https://dev.java/learn/modules/intro/ (archived as is at: https://web.archive.org/web/20260317203840/https://dev.java/learn/modules/intro/ ), and https://dev.java/learn/modules/qualified-exports-opens/ (archived as is at: https://web.archive.org/web/20260317204235/https://dev.java/learn/modules/qualified-exports-opens/ ), and https://dev.java/learn/modules/opening-for-reflection/ (archived as is at: https://web.archive.org/web/20260317204550/https://dev.java/learn/modules/opening-for-reflection/ ).
See also:
https://docs.oracle.com/javase/specs/jls/se25/jls25.pdf
Example 6.6-2. Access to public Fields, Methods, and Constructors
A public class member or constructor is accessible throughout the package where it is
declared and from any other package, provided the package in which it is declared is
observable (§7.4.3).
]
It may also be useful to mention on this page as well that the package, protected, and private access checks can sometimes be bypassed via reflection under certain conditions (see https://dev.java/learn/reflection/fields/#accessible (archived as is at: https://web.archive.org/web/20260317205612/https://dev.java/learn/reflection/fields/#accessible ) (relevant: section was added in discussion at #191 (comment) )).
Thanks so much! Feel free to leave open even if you address the above as I would also be happy to confirm any changes before closing if desired.
Activity
danthe1st commentedon Mar 17, 2026
To be honest, I am not sure whether adding that to this article would be much of an improvement.
I'd say the target group of that article doesn't need to know about modules "yet" and writing about that would just cause confusion.
JosePaumard commentedon Mar 18, 2026
Thank you again for your contribution! I just pushed a fix.
I don't want to go into too much detail on this page, since it is a section meant to introduce the dirferent levels of visibility for beginner people. So I just added a quick note that refers to the JPMS and the Reflection API. Sending all the info at once would probably scare beginners.
willy-b commentedon Mar 21, 2026
Excellent!
As of the latest "More on Classes" article, https://dev.java/learn/classes-objects/more-on-classes/#controlling-access (archived as is at https://web.archive.org/web/20260318150608/https://dev.java/learn/classes-objects/more-on-classes/#controlling-access )
the following has been added (vs old version at https://web.archive.org/web/20260317203241/https://dev.java/learn/classes-objects/more-on-classes/#controlling-access ):
Which addresses the concerns I raised for that article, thanks so much!
However, in the earlier article in the tutorial, https://dev.java/learn/classes-objects/creating-classes/#controlling-access (as of https://web.archive.org/web/20260318150146/https://dev.java/learn/classes-objects/creating-classes/#controlling-access ), there has not yet been any update to cover the effect of the Java Platform Module System or the Reflection API on access.
Note also that this "Creating Classes" article has two sections (1) "Declaring Classes" and (2) "Declaring Member Variables" before discussing access control in "Controlling who has Access to a Member" which only mentions controlling access to member fields, not to the class itself (though the effect of the module system is similar on either), covering (2) and not (1) from an access perspective.
Thus for https://dev.java/learn/classes-objects/creating-classes/#controlling-access it might be worth mentioning both class and field access (if not other types of members like methods) explicitly.
Then it may be useful to link to https://dev.java/learn/classes-objects/more-on-classes/#controlling-access from this section so that nobody risks stopping with the understanding that
Not necessarily true since the release of Modules, see JLS 25 example 6.6-2 and 7.4.3 in https://docs.oracle.com/javase/specs/jls/se25/jls25.pdf , quoted previously and again below.
Not necessarily true if reflection is used, see https://dev.java/learn/reflection/fields/#accessible (archived as is at: https://web.archive.org/web/20260317205612/https://dev.java/learn/reflection/fields/#accessible ) (relevant: section was added in discussion at #191 (comment) )
Of course you are welcome to acknowledge the above and intentionally omit it, I just want to make sure it is intentional!
Here is supporting detail for my comment on the public modifier description above, repeated for convenience and to ensure it is included in the generated email thread.
The limiting effect of the Java Platform Module System (released in Java 9 in 2017) on the public access modifier according to the JLS 25 ( https://docs.oracle.com/javase/specs/jls/se25/jls25.pdf ) is e.g.:
Where §7.4.3 is 7.4.3 Package Observability and Visibility,
which states:
Thanks so much!
willy-b commentedon Mar 23, 2026
FYI, so as to avoid confusion from possibly passing compile-time checks when considering whether the claim
is accurate (from https://dev.java/learn/classes-objects/creating-classes/#controlling-access , as of https://web.archive.org/web/20260318150146/https://dev.java/learn/classes-objects/creating-classes/#controlling-access ).
Access to public fields and methods in classes in a package which is not exported by its module from outside that module, e.g. from the unnamed module, can also be denied at runtime with IllegalAccessError (using access from the unnamed module for an extreme example, as it is highly concerning if a file updated on the classpath depended on by say an automatic module one is requiring could in its initializer access something public in your module still not intended to be used by it; I am not claiming it never can, but IllegalAccessError blocks simple attempts for non-final fields, in agreement with the JLS).
E.g. in my own testing on Java SE 21, I see when accessing public static fields and methods (not
public static finalcompile-time constant fields, though) from outside the module, e.g. from unnamed module (trying to printExample.<public static variable name>):(line breaks added to fit normal viewing width, no other edits)
The example I tested locally was to have a module which does not export or open anything require a non-modular jar on the module path (automatic module, which is allowed then to read classes on the classpath), where that non-modular jar then reads another non-modular non-jar class file on the classpath and causes an initializer there to fire which tries to access public static fields and methods of a class in the original module (in a package not exported or opened).
I was able to get past the compile-time checks in this arrangement but I do encounter the IllegalAccessError above except for accessing
public static finalcompile-time constant fields in the package not exported by a module.That is:
Whereas:
Note that the above situation is running the Java application as a modular application (recommended way since Java 9 in 2017) with main inside the module (running the modular code in a non-modular way via classpath wouldn't count).
Thanks
JosePaumard commentedon Mar 23, 2026
Thank you again for your report! I just pushed a fix.
I don't want to deep dive too much on the complete visibility rules too early in this section. As much as I agree with your comment, this is a beginner level section, and I think that talking about JPMS or Reflection at this point would only create confusion. I just added a note to say that there are exceptions, that are covered later.
willy-b commentedon Mar 23, 2026
Got it.
As of https://web.archive.org/web/20260323154257/https://dev.java/learn/classes-objects/creating-classes/#controlling-access , the added caveat:
Presumably referring to the note added to https://web.archive.org/web/20260318150608/https://dev.java/learn/classes-objects/more-on-classes/#controlling-access :
Covers the concern here, while as you noted allowing for a gradual introduction to the topic, thanks so much!