<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4" face="monospace">Interfaces are allowed to have
      (public) fields today, but they are always static.  So we're just
      talking about access control.<br>
      <br>
      My point is that I think the anomaly you are really raising is
      that access control for interface members is not uniform, but
      without a clear justification other than history.  Private
      _methods_ were introduced into interfaces in Java 8 (to go with
      default methods), but there's no good reason why private fields
      (interfaces already have fields, they are static) or private
      nested classes did not get the same treatment.  This is a topic
      for potential cleanup at some point.<br>
      <br>
      But, if I understand your clarification, you are saying: "sealed
      classes let me treat all the implementations of a type as being a
      single big implementation, and sometimes these might want to share
      state, and the sealed class is a sensible place to put state
      shared across all implementations"?  (And then taking advantage of
      the nestmate status of co-declared classes, so that "private"
      isn't really private to the interface, but private to the source
      file.)<br>
    </font><br>
    <div class="moz-cite-prefix">On 6/23/2025 8:04 AM, Swaranga Sarma
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAGZD2TCU16cnWGhuNcyTSXKYv+f35+4gSP6Mf5xwiJUZdZdsEg@mail.gmail.com">
      
      <div dir="auto">Hi Brian, I am afraid I am not seeing how I am
        making a case for private members in interfaces. That would be
        introducing state into an interface and seems pretty large
        change to the language spec. </div>
      <div dir="auto"><br>
      </div>
      <div dir="auto">As for the suggestion, yes, the post does make it
        seem like it is specific to sealed interfaces but wasn’t
        intended as such. I was using it as a real example from my work
        which uses a sealed hierarchy. Although now that I think about
        it, for regular interfaces I don’t see how it would be helpful
        if these fields are private to the interface. </div>
      <div dir="auto"><br>
      </div>
      <div dir="auto">I have felt its need more in sealed interfaces
        where I want to share common static fields and methods across
        the sub interfaces/records. <br clear="all">
        <br clear="all">
        <div dir="auto">
          <div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">
            <div dir="ltr">
              <div>Regards<br>
              </div>
              <div>Swaranga</div>
            </div>
          </div>
        </div>
      </div>
      <div><br>
      </div>
      <div><br>
        <div class="gmail_quote gmail_quote_container">
          <div dir="ltr" class="gmail_attr">On Mon, Jun 23, 2025 at
            4:50 AM Brian Goetz <<a href="mailto:brian.goetz@oracle.com" moz-do-not-send="true" class="moz-txt-link-freetext">brian.goetz@oracle.com</a>>
            wrote:<br>
          </div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)">
            <div> <font size="4" face="monospace" style="font-family:monospace;color:rgb(0,0,0)">What I
                see here is an argument for private members in
                interfaces, but this has nothing to do with sealed
                interfaces.  Why is sealing relevant to this suggestion?</font></div>
            <div><br>
              <br>
              <div>On 6/22/2025 11:18 PM, Swaranga Sarma wrote:<br>
              </div>
              <blockquote type="cite">
                <div dir="ltr">
                  <div>Traditionally Java has not allowed private static
                    members inside of an interface but now with sealed
                    interfaces, I am wondering if there is a case to be
                    made. Here is a real-world use-case where I felt
                    this was needed recently.</div>
                  <div><br>
                  </div>
                  <div>I have a sealed interface hierarchy for a simple
                    state machine transition result like below:<br>
                    <br>
                    ```</div>
                  <div>sealed interface TransitionCheckResult {</div>
                  <div>  sealed interface BootstrapTransitionCheckResult
                    extends TransitionCheckResult {</div>
                  <div>    record AllowedTransition(String
                    destinationStateId, Map<String, String>
                    metadata) {}</div>
                  <div>    record DisallowedTransition(Map<String,
                    String> metadata) {}</div>
                  <div>  }</div>
                  <div><br>
                  </div>
                  <div>  
                    <div>  sealed interface
                      IntermediateTransitionCheckResult
                      extends TransitionCheckResult {</div>
                    <div>    record AllowedTransition(String
                      destinationStateId, </div>
                    <div>                                           
                       Map<String, String> metadata, </div>
                    <div>                                           
                       List<Actions> cleanupActions) {}</div>
                    <div>    record DisallowedTransition(Map<String,
                      String> metadata) {}</div>
                    <div>  }</div>
                  </div>
                  <div>}</div>
                  <div>```</div>
                  <div><br>
                  </div>
                  <div>Basically the "transition check result" is broken
                    up into a bootstrap transition check result for the
                    initial state transition check and an "intermediary
                    transition check result" for an intermediate node in
                    the state machine each of which have their allowed
                    and disallowed transitions with slightly varying
                    attributes. So a sealed interface with records
                    seemed to fit the bill here.</div>
                  <div><br>
                  </div>
                  <div>Now for the destinationStateId, there are some
                    constraints like length and Pattern (among others).
                    I wanted to add a private static final Pattern
                    variable in the TransitionCheckResult interface
                    which I then use to validate the passed in
                    destinationStateId. But unfortunately, this is not
                    allowed. I think I have the following options none
                    of which seem great:<br>
                  </div>
                  <div>1. Make the Pattern public; no-body else needs
                    access to the Pattern field so this
                    feels unnecessary.</div>
                  <div>2. Move the pattern field to inside the record
                    class - this would work but I have two records that
                    require the same validation and either I have to
                    repeat myself or add the pattern to one of them and
                    reference it in the other. Again, feels like I
                    shouldn't have to introduce this otherwise
                    unnecessary dependency.</div>
                  <div>3. Create a DestinationStateId record where I can
                    fully encapsulate the validation in one place and
                    change the AllowedTransition record declarations to
                    use this record. This feels like the best approach
                    but then in another part of the app, I lose the
                    ability to do switch on the destinationStateId like
                    this:<br>
                    <br>
                    ```</div>
                  <div>static final RESOLVED_STATE_ID = new
                    PolicyStateId("resolved);</div>
                  <div>PolicyStateId stateId = ...;</div>
                  <div>switch(stateId.name()) {</div>
                  <div>  case RESOLVED_STATE_ID.name() -> ... // not
                    allowed</div>
                  <div>  ...</div>
                  <div>}</div>
                  <div>```</div>
                  <div>There are slight variations of these approaches
                    (like using a when clause to address the switch
                    problem or using a static inner Validator class
                    inside the top-level sealed interface) but it feels
                    verbose.</div>
                  <div><br>
                  </div>
                  <div>Thoughts? Especially now with sealed interfaces
                    and records, there could be more cases where this
                    could be useful.</div>
                  <div><br>
                  </div>
                  <div>
                    <div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">
                      <div dir="ltr">
                        <div>Regards<br>
                        </div>
                        <div>Swaranga</div>
                      </div>
                    </div>
                  </div>
                </div>
              </blockquote>
              <br>
            </div>
          </blockquote>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>