<head><!-- BaNnErBlUrFlE-HeAdEr-start -->
<style>
  #pfptBannerjasy359 { all: revert !important; display: block !important;
    visibility: visible !important; opacity: 1 !important;
    background-color: #60beeb !important;
    max-width: none !important; max-height: none !important }
  .pfptPrimaryButtonjasy359:hover, .pfptPrimaryButtonjasy359:focus {
    background-color: #77a8c4 !important; }
  .pfptPrimaryButtonjasy359:active {
    background-color: #8193a0 !important; }
  html:root, html:root>body { all: revert !important; display: block !important;
    visibility: visible !important; opacity: 1 !important; }
</style>

<!-- BaNnErBlUrFlE-HeAdEr-end -->
</head><!-- BaNnErBlUrFlE-BoDy-start -->
<!-- Preheader Text : BEGIN -->
<div style="display:none !important;display:none;visibility:hidden;mso-hide:all;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;opacity:0;overflow:hidden;">
Thank you for the thoughtful response. I agree that removing a private constructor and a few static modifiers alone would not justify introducing a new top-level construct. If this were purely about shaving off ceremony, I agree that it would</div>
<!-- Preheader Text : END -->

<!-- Email Banner : BEGIN -->
<div style="display:none !important;display:none;visibility:hidden;mso-hide:all;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;opacity:0;overflow:hidden;">ZjQcmQRYFpfptBannerStart</div>

<!--[if ((ie)|(mso))]>
  <table border="0" cellspacing="0" cellpadding="0" width="100%" style="padding: 0px 0px 10px 0px; direction: ltr" lang="en"><tr><td>
    <table border="0" cellspacing="0" cellpadding="0" style="padding: 0px 8px 6px 8px; width: 100%; border-radius:4px; border-top:4px solid #8193a0;background-color:#60beeb;"><tr><td valign="top">
      <table align="left" border="0" cellspacing="0" cellpadding="0" style="padding: 0px 8px 4px 8px; font-size: 12px; line-height: 16px">
        <tr><td style="color:#000000; font-family: 'Arial', sans-serif; font-weight:bold; font-size:14px; line-height: 20px; direction: ltr">
          This Message Is From an Untrusted Sender
        </td></tr>
        <tr><td style="color:#000000; font-weight:normal; font-family: 'Arial', sans-serif; font-size:12px; direction: ltr">
          You have not previously corresponded with this sender.
        </td></tr>

      </table>
      <![if ie]><br clear="all"><![endif]>
      <table align="right" border="0" cellspacing="0" cellpadding="0" style="padding: 0px 0px 4px 0px; font-size: 14px; line-height: 36px"><tr>
        <td style="direction: ltr">  <a target="_blank" href="https://us-phishalarm-ewt.proofpoint.com/EWT/v1/ACWV5N9M2RV99hQ!Op20OCZl8mBmmhMrd1k0lUr66H9rycR5s__cRVcFCNggENwSP-8pAB__PHFaIJ3zkle1oA92r_-R-Yw3YsXFVhqeuwimVck8CDSvpc3CicHYJhdo9Th8_8Z8U24c5yM$" style="mso-padding-alt: 7px; padding: 7px; border-radius: 2px; border: 1px solid #666666; "><strong style="font-weight: normal; color: #000000; text-decoration: none; font-family: 'Arial', sans-serif; font-size: 14px;">  Report Suspicious  </strong></a>  ‌ </td>
      </tr></table>
    </td></tr></table>
  </td></tr></table>
<![endif]-->

<![if !((ie)|(mso))]>
  <div dir="ltr" lang="en" id="pfptBannerjasy359" style="all: revert !important; display:block !important; text-align: left !important; margin: 0 0 10px 0 !important; padding:7px 16px 8px 16px !important; border-radius: 4px !important; min-width: 200px !important; background-color: #60beeb !important; background-color: #60beeb; border-top: 4px solid #8193a0 !important; border-top: 4px solid #8193a0;">
    <div id="pfptBannerjasy359" style="all: unset !important; float:left !important; display:block !important; margin: 1px 0 1px 0 !important; max-width: 600px !important;">
      <div id="pfptBannerjasy359" style="all: unset !important; display:block !important; visibility: visible !important; background-color: #60beeb !important; color:#000000 !important; color:#000000; font-family: 'Arial', sans-serif !important; font-family: 'Arial', sans-serif; font-weight:bold !important; font-weight:bold; font-size:14px !important; line-height:1.29 !important; line-height:1.29">
        This Message Is From an Untrusted Sender
      </div>
      <div id="pfptBannerjasy359" style="all: unset !important; display:block !important; visibility: visible !important; background-color: #60beeb !important; color:#000000 !important; color:#000000; font-weight:normal; font-family: 'Arial', sans-serif !important; font-family: 'Arial', sans-serif; font-size:12px !important; line-height:1.5 !important; line-height:1.5; margin-top:2px !important;">
You have not previously corresponded with this sender.
      </div>

    </div>
    <div id="pfptBannerjasy359" style="all: unset !important; float: right !important; display: block !important; display: block; margin-left: 16px !important; margin-top: 1px !important; text-align: right !important; width: fit-content !important; font-size: 12px !important">
<a id="pfptBannerjasy359" href="https://us-phishalarm-ewt.proofpoint.com/EWT/v1/ACWV5N9M2RV99hQ!Op20OCZl8mBmmhMrd1k0lUr66H9rycR5s__cRVcFCNggENwSP-8pAB__PHFaIJ3zkle1oA92r_-R-Yw3YsXFVhqeuwimVck8CDSvpc3CicHYJhdo9Th8_8Z8U24c5yM$"
    style="all: unset !important; display: inline-block !important; text-decoration: none">
    <div class="pfptPrimaryButtonjasy359" style="display: inline-block !important; display: inline-block; visibility: visible !important; opacity: 1 !important; color: #000000 !important; color: #000000; font-family: 'Arial', sans-serif !important; font-family: 'Arial', sans-serif; font-size: 14px !important;  font-weight: normal !important; text-decoration: none !important; border-radius: 2px !important; margin-top: 3px !important; margin-bottom: 3px !important; margin-left: 16px !important; padding: 7.5px 16px !important; white-space: nowrap !important; width: fit-content !important;
        border: 1px solid #666666">
        Report Suspicious
    </div>
</a>
    </div>
    <div style="clear: both !important; display: block !important; visibility: hidden !important; line-height: 0 !important; font-size: 0.01px !important; height: 0px"> </div>
  </div>
<![endif]>

<div style="display:none !important;display:none;visibility:hidden;mso-hide:all;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;opacity:0;overflow:hidden;">ZjQcmQRYFpfptBannerEnd</div>
<!-- Email Banner : END -->

<!-- BaNnErBlUrFlE-BoDy-end -->
<div dir="ltr">Thank you for the thoughtful response.<br><br>I agree that removing a private constructor and a few static modifiers alone would not justify introducing a new top-level construct. If this were purely about shaving off ceremony, I agree that it would not meet the bar.<br><br>The distinction I am trying to surface is slightly different. It is less about boilerplate and more about the semantic intent of grouping vs. the semantic intent of identity.<br><br>A class—and similarly a declared singleton—introduces a type with identity, a lifecycle, and the conceptual possibility of state. Even a "utility class" is technically a type that can be used in reflection, as a generic bounds carrier, or as a synchronization lock.<br><br>By contrast, a namespace construct would model pure structural grouping. It would allow us to group related functions and constants without also introducing the semantics of a type. In this sense, it decouples the organization of code from the object model.<br><br>I appreciate the Scala-style object direction. It is a powerful way to reify statics into the instance world. However, an object still introduces an entity with instance semantics. If I have a collection of pure, stateless mathematical functions, elevating them to an "instance" (a singleton) introduces object-model semantics that are not conceptually required for simple structural grouping.<br><br>The deeper question for Java might be: Must every grouping of code be a type?<br><br>If the answer is yes, then the Scala-style object is indeed the superior evolution. But if there is value in a "type-less" container that exists purely for structural organization, name resolution, and the developer's mental model, then a namespace offers a path that doesn't just "double down" on statics, but moves them into a more appropriate, restricted context.<br></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Wed, Feb 25, 2026 at 6:47 PM Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>

  
  <div>
    <font size="4" face="monospace">The frictions you outline here are
      real.  What's less clear is whether they are a big enough deal to
      be worth adding new top-level concepts to the language; I think
      most developers are willing to shrug this off and say "yeah, I
      have to use classes to simulate namepaces, and that means I have
      to engage in one or two bits of ceremony, but ... fine, I'll do
      that and get on with my life."  Which is an entirely pragmatic
      viewpoint; the extra boilerplate of an inaccessible constructor,
      and the sprinkling of `static`, is a relatively small bit of
      ceremony.  <br>
      <br>
      What I find uncompelling about this proposal is that it is
      _purely_ about the "code golf" of eliminating this bit of
      boilerplate, mostly doubling down on one of the weakest parts of
      the language -- static members.  It doesn't offer us any new way
      to abstract over anything, it just removes some boilerplate from
      the "bag of static members" classes.  <br>
      <br>
      If I felt these were a bigger deal, though, there is a _much_
      better solution in evidence for these problems and more: something
      like Scala's `object` declaration.  This achieves the boilerplate
      goals through solving some real semantic problems: lifecycle
      management of singletons, plus elevating static behavior to
      instance behavior.  (This strengthens statics rather than just
      doubling down on them.)<br>
      <br>
      (Notably, though, even though this solution is better in pretty
      much every way, and significantly better in some ways, I'm still
      not sure whether it meets the bar for being worth working on.)<br>
      <br>
      For those who are unfamiliar: you can declare a singleton object
      much like you do a class:<br>
      <br>
          object Patient { // could implement interfaces here <br>
              public final String PATIENT_REFERENCE_PREFIX = "Patient/";<br>
              public final Pattern PATIENT_IDENTIFIER_PATTERN =
      Pattern.compile(...);<br>
              // methods too<br>
          }<br>
      <br>
      Here, the name `Patient` is bound to the singleton _instance_, so
      you use the same use-site syntax:<br>
      <br>
          String s = Patient.PATIENT_REFERENCE_PREFIX + ...<br>
      <br>
      but instead of this being intepreted as
      <class>.<static-member>, it is interpreted as
      <instance>.<instance-member>.  So they look like
      static members, but we can abstract over them through interfaces:<br>
      <br>
          object FooBehaviors implements Comparator<Foo> { <br>
              int compare(Foo a, Foo b) { ... }<br>
          }<br>
      <br>
          ...<br>
      <br>
          foos.sort(FooBehaviors);<br>
      <br>
      (Perhaps a more familiar spelling for "object" here might be
      "singleton".)<br>
      <br>
      So:<br>
      <br>
       - Not sure the problem is worth solving<br>
       - If it is worth solving, declared singletons dominate namespaces
      by a lot<br>
       - Even with the much bigger payback of declared singletons, still
      not sure its worth solving<br>
      <br>
      <br>
    </font><br>
    <div>On 2/13/2026 8:11 AM, Øyvind Kvien
      wrote:<br>
    </div>
    <blockquote type="cite">
      
      <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><div><div dir="ltr"><code><span>public</span> <span>final</span> <span>class</span> <span>Patient</span> {

    <span>private</span> <span>Patient</span><span>()</span> {}

    <span>public</span> <span>static</span> <span>final</span> <span>String</span> <span>PATIENT_REFERENCE_PREFIX</span> <span>=</span> <span>"Patient/"</span>;
    <span>public</span> <span>static</span> <span>final</span> <span>Pattern</span> <span>PATIENT_IDENTIFIER_PATTERN</span> <span>=</span>
        Pattern.compile(<span>"^Patient/(.*)"</span>, Pattern.CASE_INSENSITIVE);

    <span>public</span> <span>record</span> <span>PatientIdentifier</span><span>(String id)</span> {}

    <span>public</span> <span>static</span> PatientIdentifier <span>getPatientIdentifier</span><span>(<span>@Nullable</span></span> Reference patientRef) {
        <span>if</span> (patientRef == <span>null</span> || patientRef.getReference() == <span>null</span>)
            <span>return</span> <span>new</span> <span>PatientIdentifier</span>(Str.EMPTY);

        <span>var</span> <span>matcher</span> <span>=</span> PATIENT_IDENTIFIER_PATTERN.matcher(patientRef.getReference());
        <span>return</span> <span>new</span> <span>PatientIdentifier</span>(matcher.find() ? matcher.group(<span>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><div><div dir="ltr"><code><span>public</span> <span>interface</span> <span>Patient</span> {
    <span>String</span> <span>PATIENT_REFERENCE_PREFIX</span> = <span>"Patient/"</span>;
    record <span>PatientIdentifier</span>(<span>String</span> id) {}
    <span>static</span> <span>PatientIdentifier</span> <span>getPatientIdentifier</span>(<span>...</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><div><div dir="ltr"><code><span>public</span> <span>namespace</span> <span>Patient</span> {

    <span>String</span> <span>PATIENT_REFERENCE_PREFIX</span> = <span>"Patient/"</span>;
    <span>Pattern</span> <span>PATIENT_IDENTIFIER_PATTERN</span> =
        <span>Pattern</span>.<span>compile</span>(<span>"^Patient/(.*)"</span>, <span>Pattern</span>.<span>CASE_INSENSITIVE</span>);

    record <span>PatientIdentifier</span>(<span>String</span> id) {}

    <span>PatientIdentifier</span> <span>getPatientIdentifier</span>(<span><span>@Nullable</span></span> <span>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>
    </blockquote>
    <br>
  </div>

</blockquote></div>