Explicit end-of-use: the 'forget' keyword

Tagir Valeev amaembo at gmail.com
Mon Jan 26 09:22:28 UTC 2026


Hello!

I think this violates the structured programming principles, as it makes
the scopes non-nested anymore. This would complicate code understanding and
refactoring (like extract method or inline method). Finally, I believe,
almost nobody would use this feature because the code works fine without
it. I agree with Remi: if you want to restrict the scope, either create a
block, or extract a method.

With best regards,
Tagir Valeev

On Mon, Jan 26, 2026 at 7:32 AM Marek Kozieł <develop4lasu at gmail.com> wrote:

> Hi,
>
> Java lacks a way to express intentional end-of-use.
>
> This leads to:
> - accidental reuse of values that are no longer semantically valid
> - unclear intent during code review
> - refactoring hazards when scopes expand
>
> I’m interested in revisiting and refining this concept (raw form was
> discussed during Project Coin in 2009). The goal is to better understand
> the problem space so that, if and when the benefits clearly justify it, a
> well-formed direction could be considered.
>
>
>
> OVERVIEW
>
> FEATURE SUMMARY:
> The forget keyword prevents further access to a variable, parameter, or
> field within a defined scope, attempts to access the variable in forbidden
> scope will result in a compile-time error.
>
> MAJOR ADVANTAGE:
> This change makes variable and resource lifetimes explicit and
> compiler-enforced, improving code clarity and predictability.
>
> MAJOR BENEFITS:
> Allows explicitly removing a variable from the active context (in terms of
> accessibility), which is currently:
>
> impossible for final variables (only comments can be used),
> impossible for method parameters (except assigning null to non-final
> references),
> impossible for fields,
> cumbersome for local variables, requiring artificial blocks (extra lines
> and indentation).
>
> Makes it possible to explicitly declare that a variable should no longer
> be used or no longer represents valid data in the current scope, including
> cases where continued use would be undesirable or error-prone (like when
> there is method created for this purpose).
> Preserves code quality over time, avoiding degradation caused by = null
> assignments, comments-only conventions, or artificial scoping blocks.
>
> MAJOR DISADVANTAGE:
> The introduction of a new reserved keyword introduces potential source
> incompatibilities with existing codebases that define identifiers named
> forget.
>
> ALTERNATIVES:
> Java currently provides only scope-based lifetime control (blocks and
> try-with-resources). It lacks a general, explicit, and compiler-enforced
> mechanism to terminate variable usability at an arbitrary point within an
> existing scope.
>
> EXAMPLES
>
> Simple and Advanced Examples:
> forget var; // Variable is forgotten for the remainder of the current
> block or method (default behavior)
> forget var : scope; // Variable is forgotten inside the entire scope
> statement
>
> where scope could potentially be : if, for, while, try, label, static,
> method
>
> forget (var1, var2, ...); // Specified variables are forgotten for the
> remainder of the current block
>
> forget this.field; // Specified field are forgotten for the remainder of
> the current block
>
> forget (var1, var2, ...) { /* code */ }; // Specified variables are
> forgotten only inside the enclosed block
>
> void handleRequest(String request, String token) {    if
> (!isTokenValid(token)) {
>       throw new SecurityException("Invalid token");
>    }
>
>    authorize(request, token);
>
>    forget token /* used & contains sensitive info */;
>
>    process(request);
>
>    logger.debug("token was: " + token); // Compile-time error: 'token' has
> been forgotten and cannot be used
> }
>
> public Product(String name) { // constructor
>    this.name = name.trim().intern();
>    forget name; // From now on, only use 'this.name'!
>
>    // other constructor commands...
>
>    if (isDuplicate(this.name)) { ... } // Always canonical, never raw
> input
>    if (isDuplicate(name)) { ... } // Compile-time ERROR!
> }
>
>    // * Forces usage of the correctly prepared value (this.name) only.
>    // * Prevents code drift, maintenance bugs, or copy-paste errors that
> reference the raw parameter.
>    // * Makes the constructor safer: no risk of mismatches or inconsistent
> logic.
>    // * Reads as a contract: "from here on, don't touch the original
> argument!"
> Next Version Examples:
> forget ClassName.field;
> forget variable.field;
> forget (!variable); // Limit allowed variables to ones that are directly
> specified
>
> DETAILS
>
> SPECIFICATION:
>    forget [ Identifier | ( IdentifierList ) ] [ : Scope | { block }];
>
>    IdentifierList:
>    Identifier {, Identifier}
>
>    Identifier:
>    [ VariableIdentifier | this.FieldIdentifier ]
>
> The forget statement forbids any further use of the specified identifier
> in all subsequent expressions and statements within the declared scope in
> which the identifier would normally be accessible.
>
> COMPILATION:
> The variable is not physically erased (except it may be if not a field);
> rather, it is protected from any further access after the forget statement.
> Additionally, retaining the variable in the scope (but inaccessible)
> prevents situations where a developer tries to create a new variable with
> the same name after removing the forget statement, thereby enforcing
> consistent usage and avoiding hidden bugs.
>
> TESTING:
> Testing the forget statement is equivalent to testing variable scope after
> exiting a block—the variable becomes inaccessible. For fields, forget
> enforces access control, ensuring the field cannot be used within the
> specified scope for the remainder of its block or method.LIBRARY
>
> COMPATIBILITY
> The introduction of a new keyword (forget) may cause conflicts in
> codebases where forget is already used as an identifier. There are no other
> compatibility impacts.
>
> REFERENCES
> Current draft  »
> https://lasu2string.blogspot.com/2026/01/Java-forget-keyword.html
> Reddit discussion »
> https://www.reddit.com/r/java/comments/1qhhf9y/proposal_introducing_the_forget_keyword_in_java/
> Draft from 2009  »
> https://lasu2string.blogspot.com/2009/03/forget-keyword-proposal_27.html
> Project coin 2009 discussion entry  »
> https://mail.openjdk.org/pipermail/coin-dev/2009-March/001093.html
> JDK-6189163  » https://bugs.openjdk.org/browse/JDK-6189163
>
>
> PROBLEMS
>
> Backward Compatibility: Introducing forget as a new reserved keyword will
> cause compilation errors in existing code that already uses forget as an
> identifier (variable, method, class, etc).
> Tooling Lag: IDEs, static analysis tools, and debuggers must all be
> updated to handle the new keyword and its effects on variable visibility.
> Code Readability: Misuse or overuse of forget could make code harder to
> maintain or follow if not used judiciously, especially if variables are
> forgotten in non-obvious places.
> Teaching and Onboarding: This feature introduces a new concept that must
> be documented and taught to all developers, which can increase the learning
> curve for Java.
> Migration Complexity: Automatic migration of legacy code may be
> challenging, particularly for projects that rely on forget as an existing
> identifier or which have established conventions for variable lifetime.
> Interaction with Scoping and Shadowing: The detailed behavior when
> variables are forgotten, shadowed, or reintroduced in inner scopes may lead
> to confusion and subtle bugs if not carefully specified and implemented.
> Reflection and Debugging: While reflective APIs themselves are not
> impacted, developers may be surprised by the presence of variables at
> runtime (for debugging or reflection) that are "forgotten" in the source
> code.
> Consistency Across Language Features: Defining consistent behavior for
> forget in new contexts (e.g., lambdas, anonymous classes, record classes)
> may require extra specification effort.
> Edge Cases and Specification Complexity: Fully specifying the semantics of
> forget for all cases—including fields, parameters, captured variables in
> inner/nested classes, and interaction with try/catch/finally—may be complex.
> Unused Feature Risk: There is a risk that the forget keyword will see
> little real-world use, or will be misunderstood, if not supported and
> encouraged by frameworks or coding standards.
>
> THE RIGHT AND THE WRONG WAY
>
> During the discussion, it became clear that the main conception of usage
> was not approached from the right angle.
> For example, the request JDK-6189163: New language feature: undeclare
> operator made a similar suggestion. Unfortunately, much of the focus was on
> "destroying" variables as a matter of code complexity and maintenance. This
> focus is problematic for several reasons:
>
> The compiler can already release variables when they are no longer needed.
> Focusing on disposing bytes of data is really a bad step as it shouldn't
> be a concern in the first place.
> Focusing on variable usability in this way actually decreases
> maintainability, since both current and future modifications would require
> additional checks to unlock variables or identify where a variable has been
> "undeclared" in the middle of code. This complicates code changes
> unnecessarily.
>
>
>
> At the same time, we should highlight that many language features are, to
> some extent, syntactic sugar from a usability perspective:
>
> Block-based local variable scoping
>  - Enhanced for Loop
>  - Final guard
>  - Generics
>  - Lambdas
>  - Records
>  - Switch Expressions
>  - Text Blocks
>  - Try-With-Resources
>  - ... and many more
>
> Each of these features can absolutely be used in the wrong way, which may
> decrease code quality.
> On the other hand, when used properly, they can significantly reduce
> cognitive load and the time required for analysis, refactoring, and
> modification - and this path the change will aim to follow.
>
> So we should focus on situations where forget is actually beneficial in
> the short or long term:
>
> When code is actively being developed -especially complex one - there are
> situations where removing unnecessary variables from the context is
> beneficial. It's entirely possible that in the final version these
> variables will be placed into proper scopes with no need of forget, but
> until then forget would serve an important purpose during development.
> When modifying long or complex code—especially if an issue arises from the
> incorrect reuse of a variable: We could safeguard the variable with a
> comment explaining its intended use and the change made. This targeted fix
> is preferable to an unannotated quick fix (which leaves confusion for
> future maintainers) or an extensive refactor, which could disrupt code
> history and introduce new errors.
> Writing security-sensitive code where resources need to be released in a
> specific order that cannot be enforced using classic block structures.
> Explicitly excluding class variables from the current method scope when
> ussage could be harmfull(for example in efficiency aspect), helping to
> prevent accidental usage and improve code clarity.
>
>
>
> SIMPLIFIED VERSION
>
> Problem: Handling variable "forgetting" via scope control can introduce
> unnecessary complexity. To address this, an alternative version without
> scope customization could be considered.
>
> Simplified Solution:
>
> Instead of customizing scopes, forget could apply to the method/block
> scope.
> Caveat: It does NOT work for mutually exclusive scopes like parallel
> branches (if-else, switch-case). In those, you must restate forget in each
> branch.
>
> void handleRequest(String request, String token) {
>    if (!isTokenValid(token)) {
>       throw new SecurityException("Invalid token");
>    }
>    if (forceLogOut()){
>       logOut(request, token);
>       forget token; // prevent usage in the rest of this block and after
> the if-else
>       ...
>    } else {
>       authorize(request, token);
>       forget token; // 'forget' needs to be restated here
>       ...
>    }
>    logger.debug("token was: " + token); // Compile-time error!
> }
> This approach is more rigid and resistant to refactoring mistakes if block
> scopes change.
> If more flexibility is needed, a more complex form like forget var :
> label; (for better control) can be introduced as an advanced feature.
>
> SUMMARY
>
> The forget keyword represents a natural evolution of Java's commitment to
> clear, explicit, and compiler-enforced language rules. By allowing
> developers to mark variables, parameters, or fields as no longer usable
> within a defined scope, forget makes variable lifetimes and resource
> management visible and deliberate. This approach eliminates ambiguity in
> code, prevents accidental misuse, and reinforces Java’s tradition of making
> correctness and safety a language guarantee, not just a convention. Like
> Java’s robust type system and scoping mechanisms, forget enhances code
> clarity, maintainability, and reliability.
>
> --
> Greetings
> Marek Kozieł ( Lasu )
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20260126/32345675/attachment-0001.htm>


More information about the amber-dev mailing list