Private static members in sealed-interfaces?

Swaranga Sarma sarma.swaranga at gmail.com
Mon Jun 23 12:04:44 UTC 2025


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.

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.

I have felt its need more in sealed interfaces where I want to share common
static fields and methods across the sub interfaces/records.

Regards
Swaranga


On Mon, Jun 23, 2025 at 4:50 AM Brian Goetz <brian.goetz at oracle.com> wrote:

> 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?
>
>
> On 6/22/2025 11:18 PM, Swaranga Sarma wrote:
>
> 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.
>
> I have a sealed interface hierarchy for a simple state machine transition
> result like below:
>
> ```
> sealed interface TransitionCheckResult {
>   sealed interface BootstrapTransitionCheckResult
> extends TransitionCheckResult {
>     record AllowedTransition(String destinationStateId, Map<String,
> String> metadata) {}
>     record DisallowedTransition(Map<String, String> metadata) {}
>   }
>
>
>   sealed interface IntermediateTransitionCheckResult
> extends TransitionCheckResult {
>     record AllowedTransition(String destinationStateId,
>                                              Map<String, String> metadata,
>                                              List<Actions> cleanupActions)
> {}
>     record DisallowedTransition(Map<String, String> metadata) {}
>   }
> }
> ```
>
> 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.
>
> 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:
> 1. Make the Pattern public; no-body else needs access to the Pattern field
> so this feels unnecessary.
> 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.
> 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:
>
> ```
> static final RESOLVED_STATE_ID = new PolicyStateId("resolved);
> PolicyStateId stateId = ...;
> switch(stateId.name()) {
>   case RESOLVED_STATE_ID.name() -> ... // not allowed
>   ...
> }
> ```
> 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.
>
> Thoughts? Especially now with sealed interfaces and records, there could
> be more cases where this could be useful.
>
> Regards
> Swaranga
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20250623/227dc73c/attachment.htm>


More information about the amber-dev mailing list