106

I've just replaced s in the following lambda expression by _:

s -> Integer.parseInt(s)

Eclipse compiler says:

'_' should not be used as an identifier, since it is a reserved keyword from source level 1.8 on.

I haven't found any explanation in the JLS §3.9 Lexical Structure / Keywords.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Aubin
  • 14,617
  • 9
  • 61
  • 84

4 Answers4

92

The place to look is JLS §15.27.1. Lambda Parameters

It is a compile-time error if a lambda parameter has the name _ (that is, a single underscore character).

The use of the variable name _ in any context is discouraged. Future versions of the Java programming language may reserve this name as a keyword and/or give it special semantics.

So the Eclipse message is misleading, especially as the same message is used for both cases, when an error is generated for a lambda parameter or when a warning is generated for any other _ identifier.

Community
  • 1
  • 1
Holger
  • 285,553
  • 42
  • 434
  • 765
  • 27
    Note that as of Java 9, `_` will be disallowed as any legal identifier names and not only as a lambda parameter name. This was actually fixed in build 43 : https://bugs.openjdk.java.net/browse/JDK-8061549 – Jean-François Savard Jul 09 '15 at 22:14
  • 2
    I can't find any reference as to why? – lscoughlin Jul 27 '15 at 12:52
  • 4
    @lscoughlin: Isn’t “Future versions of the Java programming language may reserve this name as a keyword and/or give it special semantics” statement enough? Well, replace “may reserve” by “will use”, and you’ll get the picture. Maybe [this mail reference](http://mail.openjdk.java.net/pipermail/lambda-dev/2013-July/010670.html) helps… – Holger Jul 27 '15 at 12:57
  • 1
    @Holger, yeah -- helps a little. It just seems so odd and arbitrary to me. – lscoughlin Jul 27 '15 at 14:29
  • 3
    @lscoughlin: it seems to be inspired by the Scala programming language. Besides being close to other languages, it don’t see any reason to deprecate an identify instead of using one of the currently unused special characters, say `#`, `§`, or `¶` – Holger Jul 27 '15 at 14:42
  • 11
    What is this? Java breaking backwards compatibility? – Arturo Torres Sánchez Jul 27 '15 at 17:44
  • 11
    @Arturo Torres Sánchez: that’s nothing new. There were times when `enum` and `assert` were legal identifiers… – Holger Jul 27 '15 at 17:52
  • @Holger I know where it comes from i just find it odd, especially in it's extremely limited nature. And I completely agree with you about there being plenty of other characters or character combinations left that would work just fine with out being out place if used in other contexts ( @, ^, or even '..' come to mind ) . – lscoughlin Jul 28 '15 at 12:40
  • 12
    @Holger actually there are tons of languages that use underscore as a name placeholder (Scala, Clojure, F#, SML, Erlang, just to name a few). It's an established pattern that traces back to 90s or 80s, I believe, so disobeying it is odd. – om-nom-nom Jul 28 '15 at 20:59
  • 3
    Apples Swift uses an underscore. The underscore can be placed before method argument names. It makes writing variable names unnecessary when calling methods. – ASA Oct 30 '15 at 08:07
  • _So much for backwards compatibility._ – Sapphire_Brick Jun 26 '20 at 17:53
  • 2
    For the record, it's a _compile-time_ compatibility break. This doesn't break runtime backwards-compatibility for existing classes. – William Price Jan 16 '22 at 17:02
35

It is the Phase 2 of JEP 302, that is going to add underscore as a special character to denote unused parameters in lambda expressions.

Treatment of underscores

In many languages, it is common to use an underscore (_) to denote an unnamed lambda parameter (and similarly for method and exception parameters):

BiFunction<Integer, String, String> biss = (i, _) -> String.valueOf(i);

This allows stronger static checking of unused arguments, and also allows multiple arguments to be marked as unused. However, because underscore was a valid identifier as of Java 8, compatibility required us to take a more indirect path to getting to where underscore could serve this role in Java. Phase 1 was forbidding underscore as a lambda formal parameter name in Java 8 (this had no compatibility consequence, since lambdas did not exist previously) and a warning was issued for using underscore as an identifier in other places. Phase 2 came in Java 9, when this warning became an error. We are now free to complete the planned rehabilitation of underscore to indicate an unused lambda, method, or catch formal parameter.

  • 3
    This usage is discussed by Brian Goetz in [his Devoxx talk of 2017-11](https://youtu.be/qul2B8iPC-o?t=43m1s) about [Project Amber](http://openjdk.java.net/projects/amber/). – Basil Bourque Sep 18 '18 at 08:41
  • OK, but what is the alternative to denote unused parameters in J8? Is that not possible at all? – Manuel Oct 25 '19 at 20:49
  • 2
    We currently use `$` for this purpose. – aventurin Dec 19 '19 at 11:38
  • 9
    I'm on Java 14 now, and I still cannot use an underscore as an unnamed lambda parameter. Whatever the JCP set out to achieve, it appears they have achieved the opposite. – Frans Jun 08 '20 at 07:55
  • 1
    @Frans Note that the JEP is (as of today) only in candidate stage. It has not been completed yet. For more details on the JEP process see [JEP 1](https://openjdk.java.net/jeps/1) – Alexandre de Champeaux Jun 08 '20 at 23:35
  • 1
    @AlexandredeChampeaux The original comment was from 2014 so it seemed reasonable to assume that both phases would have been completed. I don't quite see the merits of disallowing an underscore only to allow it again later (albeit with slightly different semantics) but I guess the wise men had their reasons. – Frans Jun 09 '20 at 11:24
  • 1
    @Manuel I like to use two underscores as an unused parameter, but I've never seen anyone else do that. – Sapphire_Brick Jun 08 '21 at 23:07
7

Java Language Changes for Java SE 9 https://docs.oracle.com/javase/9/language/toc.htm#JSLAN-GUID-16A5183A-DC0D-4A96-B9D8-AAC9671222DD

From Java 9, the _ character cannot be used as an identifier anymore, not just within the lambda context

The underscore character is not a legal name.

If you use the underscore character ("_") an identifier, your source code can no longer be compiled.

Community
  • 1
  • 1
Angel Koh
  • 12,479
  • 7
  • 64
  • 91
2

tl;dr

As Java evolves, the underscore character takes on a special new meaning: elide the type and name of a record component.

Underscore = eliding type and name

As a preview feature in Java 21, we see the underscore character used to:

  • elide the type and name of a record component in pattern matching.
  • elide the identifier which follows the type or var in a type pattern.

See JEP 443: Unnamed Patterns and Variables (Preview).

Underscore as identifier disallowed in Java 9+

The underscore character (_) is code point 95 decimal, 5F hex. Formally named LOW LINE in the Unicode standard.

Using underscore as an identifier throws:

  • a warning in Java 8.
  • an error in Java 9+.

See: JEP 213: Milling Project Coin.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154