Packages, modules, reflection, and annotations
Packages organize names. The Java Platform Module System adds explicit dependencies and strong encapsulation.
Packages
Package names should follow stable ownership and capability.
Package-private visibility is a useful architectural boundary. Avoid
dumping unrelated types into util.
Modules
A module descriptor can requires another module,
exports packages to consumers, opens packages
for deep reflection, uses services, and
provides implementations. exports is
compile/runtime access; opens permits reflective
access.
The module path uses named modules. The classpath places code in the
unnamed module. Automatic modules help migration but names and
boundaries need care. jlink can create a custom runtime
containing selected modules.
Reflection
Reflection inspects and invokes types dynamically. It enables frameworks, serialization, tests, and tools, but weakens compile-time visibility and can cross encapsulation only with allowed access. Cache reflective metadata when appropriate and avoid using reflection to hide normal design.
Annotations
Retention can be SOURCE, CLASS, or RUNTIME. Targets restrict where annotations apply. Annotation processors generate/validate code at compile time; reflection reads runtime annotations.
ServiceLoader
The service-provider mechanism discovers implementations without
hard-coding them. Modules can declare uses and
provides.
Feynman check
A package is a labeled room. A module is a building permit listing
which rooms outsiders may enter and which other buildings it depends on.
opens grants a special inspector access.