<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font face="monospace" size="4">OK, good.  SO the good news is that
      we agree that the current asymmetric treatment of private
      methods-but-not-other-members in interfaces should be fixed.  The
      bad news is that it is not anywhere near the top of anyone's
      priority list :(<br>
      <br>
      <br>
    </font><br>
    <div class="moz-cite-prefix">On 6/23/2025 11:12 AM, Swaranga Sarma
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAGZD2TA_vPXtkpb8Uh5-HVhq6TqdwnTu0on=0vFeDtXbCMU3kA@mail.gmail.com">
      
      <div dir="ltr">
        <div>Ah, yes. When you said members, I was thinking of
          non-static instance fields. Yes, this is all about access
          control. </div>
        <div><br>
        </div>
        <div>> <font size="4" face="monospace">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.</font></div>
        <div>
          <div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">
            <div dir="ltr">
              <div>Thank you.</div>
              <div><br>
              </div>
              <div>> <font size="4" face="monospace">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.)</font></div>
              <div>Yes, a much better way to say what I was trying to
                emphasize with my example using the sealed classes
                hierarchy.</div>
              <div><br>
              </div>
              <div>Regards<br>
              </div>
              <div>Swaranga</div>
            </div>
          </div>
        </div>
        <br>
      </div>
      <br>
      <div class="gmail_quote gmail_quote_container">
        <div dir="ltr" class="gmail_attr">On Mon, Jun 23, 2025 at
          5:19 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:1px solid rgb(204,204,204);padding-left:1ex">
          <div> <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>On 6/23/2025 8:04 AM, Swaranga Sarma wrote:<br>
            </div>
            <blockquote type="cite">
              <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">
                    <div dir="ltr">
                      <div>Regards<br>
                      </div>
                      <div>Swaranga</div>
                    </div>
                  </div>
                </div>
              </div>
              <div><br>
              </div>
              <div><br>
                <div class="gmail_quote">
                  <div dir="ltr" class="gmail_attr">On Mon, Jun 23, 2025
                    at 4:50 AM Brian Goetz <<a href="mailto:brian.goetz@oracle.com" target="_blank" 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:1px solid rgb(204,204,204);padding-left:1ex">
                    <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">
                              <div dir="ltr">
                                <div>Regards<br>
                                </div>
                                <div>Swaranga</div>
                              </div>
                            </div>
                          </div>
                        </div>
                      </blockquote>
                      <br>
                    </div>
                  </blockquote>
                </div>
              </div>
            </blockquote>
            <br>
          </div>
        </blockquote>
      </div>
    </blockquote>
    <br>
  </body>
</html>