<!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>