[SPAM] Explicit end-of-use: the 'forget' keyword

Remi Forax forax at univ-mlv.fr
Mon Jan 26 07:59:51 UTC 2026


Hello Marek, 
usually, if you are not able to track the lifetime of a variable by just reading the code, it means that the code as to be changed/refactored, not complexified by adding yet another keyword. 

For local variables, in any C like language, if you want to reduce the scope of a variable, just add a block 

void foo() { 
int a = 3; 
{ // reduce the visibility of all the variable declared inside that block 
int b = 4; 
} 
// b is not accessible here 
} 

Also, in JavaScript, there is an operator "delete" [1] which has very a similar semantics to what you are proposing, that was deprecated when the strict mode was introduced (EcmaScript 5, 2015). 

regards, 
Rémi 

[1] [ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete | https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete  ] 

PS: you are wrong that in a constructor once you have initialized a field, you do not want to access to the local variable/parameter used for initializing that variable. 
(see JEP 513: [ https://openjdk.org/jeps/513 | https://openjdk.org/jeps/513 ] ) 

> From: "Marek Kozieł" <develop4lasu at gmail.com>
> To: "amber-dev" <amber-dev at openjdk.org>
> Sent: Monday, January 26, 2026 7:31:31 AM
> Subject: [SPAM] Explicit end-of-use: the 'forget' keyword

> 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
> [ http://this.name/ | this.name ] = name.trim().intern();
> forget name; // From now on, only use ' [ http://this.name/ | this.name ] '!

> // other constructor commands...

> if (isDuplicate( [ http://this.name/ | this.name ] )) { ... } // Always
> canonical, never raw input
> if (isDuplicate(name)) { ... } // Compile-time ERROR!
> }

> // * Forces usage of the correctly prepared value ( [ http://this.name/ |
> 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 |
> 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/
> |
> 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 |
> 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 |
> https://mail.openjdk.org/pipermail/coin-dev/2009-March/001093.html ]
> JDK-6189163 » [ https://bugs.openjdk.org/browse/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/f8dea316/attachment-0001.htm>


More information about the amber-dev mailing list