<div dir="ltr"><p>Dear Amber team,</p>
<p>I would like to explore the idea of introducing a first-class namespace construct in Java, intended to support data-oriented and functional programming styles without repurposing classes or interfaces as containers for static members.</p>
<p>Motivation</p>
<p>In data-oriented and mostly functional Java codebases, it is common to group:</p>
<ul>
<li>
<p>Stateless utility functions</p>
</li>
<li>
<p>Related constants</p>
</li>
<li>
<p>Small domain records</p>
</li>
<li>
<p>Parsing and validation logic</p>
</li>
</ul>
<p>Today, the idiomatic way to express this grouping is:</p>
<pre class="gmail-overflow-visible! gmail-px-0!"><div class="gmail-contain-inline-size gmail-rounded-2xl gmail-corner-superellipse/1.1 gmail-relative gmail-bg-token-sidebar-surface-primary"><div class="gmail-sticky gmail-top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"><div class="gmail-absolute end-0 gmail-bottom-0 gmail-flex gmail-h-9 gmail-items-center gmail-pe-2"><div class="gmail-bg-token-bg-elevated-secondary gmail-text-token-text-secondary gmail-flex gmail-items-center gmail-gap-4 gmail-rounded-sm gmail-px-2 gmail-font-sans gmail-text-xs"></div></div></div><div class="gmail-overflow-y-auto gmail-p-4" dir="ltr"><code class="gmail-whitespace-pre!"><span class="gmail-hljs-keyword">public</span> <span class="gmail-hljs-keyword">final</span> <span class="gmail-hljs-keyword">class</span> <span class="gmail-hljs-title gmail-class_">Patient</span> {

    <span class="gmail-hljs-keyword">private</span> <span class="gmail-hljs-title gmail-function_">Patient</span><span class="gmail-hljs-params">()</span> {}

    <span class="gmail-hljs-keyword">public</span> <span class="gmail-hljs-keyword">static</span> <span class="gmail-hljs-keyword">final</span> <span class="gmail-hljs-type">String</span> <span class="gmail-hljs-variable">PATIENT_REFERENCE_PREFIX</span> <span class="gmail-hljs-operator">=</span> <span class="gmail-hljs-string">"Patient/"</span>;
    <span class="gmail-hljs-keyword">public</span> <span class="gmail-hljs-keyword">static</span> <span class="gmail-hljs-keyword">final</span> <span class="gmail-hljs-type">Pattern</span> <span class="gmail-hljs-variable">PATIENT_IDENTIFIER_PATTERN</span> <span class="gmail-hljs-operator">=</span>
        Pattern.compile(<span class="gmail-hljs-string">"^Patient/(.*)"</span>, Pattern.CASE_INSENSITIVE);

    <span class="gmail-hljs-keyword">public</span> <span class="gmail-hljs-keyword">record</span> <span class="gmail-hljs-title gmail-class_">PatientIdentifier</span><span class="gmail-hljs-params">(String id)</span> {}

    <span class="gmail-hljs-keyword">public</span> <span class="gmail-hljs-keyword">static</span> PatientIdentifier <span class="gmail-hljs-title gmail-function_">getPatientIdentifier</span><span class="gmail-hljs-params">(<span class="gmail-hljs-meta">@Nullable</span></span> Reference patientRef) {
        <span class="gmail-hljs-keyword">if</span> (patientRef == <span class="gmail-hljs-literal">null</span> || patientRef.getReference() == <span class="gmail-hljs-literal">null</span>)
            <span class="gmail-hljs-keyword">return</span> <span class="gmail-hljs-keyword">new</span> <span class="gmail-hljs-title gmail-class_">PatientIdentifier</span>(Str.EMPTY);

        <span class="gmail-hljs-type">var</span> <span class="gmail-hljs-variable">matcher</span> <span class="gmail-hljs-operator">=</span> PATIENT_IDENTIFIER_PATTERN.matcher(patientRef.getReference());
        <span class="gmail-hljs-keyword">return</span> <span class="gmail-hljs-keyword">new</span> <span class="gmail-hljs-title gmail-class_">PatientIdentifier</span>(matcher.find() ? matcher.group(<span class="gmail-hljs-number">1</span>) : Str.EMPTY);
    }
}
</code></div></div></pre>
<p>This works, but it introduces conceptual and syntactic friction:</p>
<ul>
<li>
<p>The type is not meant to be instantiated.</p>
</li>
<li>
<p>The constructor must be manually suppressed.</p>
</li>
<li>
<p>Everything must be explicitly marked static.</p>
</li>
<li>
<p>The type is not modeling an object or abstraction; it is modeling a namespace.</p>
</li>
</ul>
<p>In practice, such classes act as packages within packages.</p>
<p>An alternative is to use an interface as a namespace:</p>
<pre class="gmail-overflow-visible! gmail-px-0!"><div class="gmail-contain-inline-size gmail-rounded-2xl gmail-corner-superellipse/1.1 gmail-relative gmail-bg-token-sidebar-surface-primary"><div class="gmail-sticky gmail-top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"><div class="gmail-absolute end-0 gmail-bottom-0 gmail-flex gmail-h-9 gmail-items-center gmail-pe-2"><div class="gmail-bg-token-bg-elevated-secondary gmail-text-token-text-secondary gmail-flex gmail-items-center gmail-gap-4 gmail-rounded-sm gmail-px-2 gmail-font-sans gmail-text-xs"></div></div></div><div class="gmail-overflow-y-auto gmail-p-4" dir="ltr"><code class="gmail-whitespace-pre!"><span class="gmail-hljs-keyword">public</span> <span class="gmail-hljs-keyword">interface</span> <span class="gmail-hljs-title gmail-class_">Patient</span> {
    <span class="gmail-hljs-title gmail-class_">String</span> <span class="gmail-hljs-variable gmail-constant_">PATIENT_REFERENCE_PREFIX</span> = <span class="gmail-hljs-string">"Patient/"</span>;
    record <span class="gmail-hljs-title gmail-class_">PatientIdentifier</span>(<span class="gmail-hljs-title gmail-class_">String</span> id) {}
    <span class="gmail-hljs-keyword">static</span> <span class="gmail-hljs-title gmail-class_">PatientIdentifier</span> <span class="gmail-hljs-title gmail-function_">getPatientIdentifier</span>(<span class="gmail-hljs-params">...</span>) { ... }
}
</code></div></div></pre>
<p>However, interfaces are primarily intended to model polymorphic contracts and substitution. Repurposing them as namespace containers can blur intent and introduce conceptual confusion. The well-known “constant interface” anti-pattern illustrates this discomfort.</p>
<p>In short, Java lacks a first-class way to express “this is a namespace for related functions and data types.”</p>
<p>Design Goal</p>
<p>Provide a language-level construct that:</p>
<ul>
<li>
<p>Represents a pure namespace (not a type with identity).</p>
</li>
<li>
<p>Cannot be instantiated or extended.</p>
</li>
<li>
<p>Groups related functions, constants, and nested types.</p>
</li>
<li>
<p>Supports access modifiers.</p>
</li>
<li>
<p>Avoids boilerplate such as private constructors and repeated static.</p>
</li>
<li>
<p>Preserves Java’s explicitness and readability.</p>
</li>
</ul>
<p>Strawman Syntax</p>
<p>One possible direction:</p>
<pre class="gmail-overflow-visible! gmail-px-0!"><div class="gmail-contain-inline-size gmail-rounded-2xl gmail-corner-superellipse/1.1 gmail-relative gmail-bg-token-sidebar-surface-primary"><div class="gmail-sticky gmail-top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"><div class="gmail-absolute end-0 gmail-bottom-0 gmail-flex gmail-h-9 gmail-items-center gmail-pe-2"><div class="gmail-bg-token-bg-elevated-secondary gmail-text-token-text-secondary gmail-flex gmail-items-center gmail-gap-4 gmail-rounded-sm gmail-px-2 gmail-font-sans gmail-text-xs"></div></div></div><div class="gmail-overflow-y-auto gmail-p-4" dir="ltr"><code class="gmail-whitespace-pre!"><span class="gmail-hljs-keyword">public</span> <span class="gmail-hljs-keyword">namespace</span> <span class="gmail-hljs-title gmail-class_">Patient</span> {

    <span class="gmail-hljs-title gmail-class_">String</span> <span class="gmail-hljs-variable gmail-constant_">PATIENT_REFERENCE_PREFIX</span> = <span class="gmail-hljs-string">"Patient/"</span>;
    <span class="gmail-hljs-title gmail-class_">Pattern</span> <span class="gmail-hljs-variable gmail-constant_">PATIENT_IDENTIFIER_PATTERN</span> =
        <span class="gmail-hljs-title gmail-class_">Pattern</span>.<span class="gmail-hljs-title gmail-function_">compile</span>(<span class="gmail-hljs-string">"^Patient/(.*)"</span>, <span class="gmail-hljs-title gmail-class_">Pattern</span>.<span class="gmail-hljs-property">CASE_INSENSITIVE</span>);

    record <span class="gmail-hljs-title gmail-class_">PatientIdentifier</span>(<span class="gmail-hljs-title gmail-class_">String</span> id) {}

    <span class="gmail-hljs-title gmail-class_">PatientIdentifier</span> <span class="gmail-hljs-title gmail-function_">getPatientIdentifier</span>(<span class="gmail-hljs-params"><span class="gmail-hljs-meta">@Nullable</span></span> <span class="gmail-hljs-title gmail-class_">Reference</span> patientRef) {
        ...
    }
}
</code></div></div></pre>
<p>Semantics (strawman)</p>
<ul>
<li>
<p>namespace introduces a named scope at top level.</p>
</li>
<li>
<p>Members are implicitly static.</p>
</li>
<li>
<p>Fields are implicitly static final unless specified otherwise.</p>
</li>
<li>
<p>Nested types are implicitly static.</p>
</li>
<li>
<p>The namespace itself:</p>
<ul>
<li>
<p>Cannot be instantiated.</p>
</li>
<li>
<p>Cannot implement or extend anything.</p>
</li>
<li>
<p>Cannot declare instance state.</p>
</li>
</ul>
</li>
<li>
<p>Initialization semantics follow class static initialization rules.</p>
</li>
<li>
<p>At the bytecode level, the namespace may be compiled to a synthetic final class, preserving JVM compatibility.</p>
</li>
</ul>
<p>Why Not Just Use Classes?</p>
<p>Using final classes with private constructors is serviceable but semantically misleading:</p>
<ul>
<li>
<p>A class suggests instantiability, inheritance relationships, or type abstraction.</p>
</li>
<li>
<p>Namespace-only classes are often flagged as utility classes.</p>
</li>
<li>
<p>The pattern is common enough that it arguably deserves first-class support.</p>
</li>
</ul>
<p>Why Not Just Use Interfaces?</p>
<p>Interfaces are designed primarily for polymorphic abstraction. Using them as namespace containers:</p>
<ul>
<li>
<p>Conflates two distinct concepts (contract vs grouping).</p>
</li>
<li>
<p>Introduces ambiguity in API design intent.</p>
</li>
<li>
<p>Encourages patterns that may confuse less experienced developers.</p>
</li>
</ul>
<p>Providing a dedicated construct allows interfaces to remain focused on substitution and abstraction.</p>
<p>Interaction With Existing Features</p>
<p>Questions for exploration include:</p>
<ul>
<li>
<p>Should namespace members require explicit static, or be implicitly static?</p>
</li>
<li>
<p>Should access modifiers default to the namespace’s modifier?</p>
</li>
<li>
<p>How do annotations apply to the namespace?</p>
</li>
<li>
<p>Should nested namespaces be allowed?</p>
</li>
<li>
<p>How does reflection expose namespaces?</p>
</li>
<li>
<p>How should Javadoc render them?</p>
</li>
</ul>
<p>A minimal version could require explicit modifiers and treat namespaces as a restricted form of top-level type compiled to a synthetic final class.</p>
<p>Summary</p>
<p>As Java evolves toward stronger support for data-oriented programming (records, pattern matching, etc.), it may be worth revisiting how we express stateless domain logic and function groupings.</p>
<p>A first-class namespace construct could:</p>
<ul>
<li>
<p>Reduce boilerplate.</p>
</li>
<li>
<p>Clarify intent.</p>
</li>
<li>
<p>Preserve the role of classes and interfaces.</p>
</li>
<li>
<p>Improve expressiveness for functional-style Java.</p>
</li>
</ul>
<p>I would be interested in feedback on:</p>
<ol>
<li>
<p>Whether this problem is considered significant enough.</p>
</li>
<li>
<p>Whether a namespace construct fits Java’s philosophy.</p>
</li>
<li>
<p>Whether there are smaller or more incremental ways to address the issue.</p>
</li>
</ol>
<p>Best regards,<br>Øyvind Kvien</p><p><br></p></div>