官方原文(英文)地址:
https://openjdk.java.net/jeps/375
个人原创翻译,转载请注明出处。
Enhance the Java programming language with pattern matching for the instanceof
operator. Pattern matching allows common logic in a program, namely the conditional extraction of components from objects, to be expressed more concisely and safely. This is a preview language feature in JDK 15.
Pattern matching for instanceof
was proposed by JEP 305 in mid 2017, and targeted to JDK 14 in late 2019 as a preview language feature. This JEP proposes to re-preview the feature in JDK 15, with no changes relative to the preview in JDK 14, in order to gather additional feedback.
Nearly every program includes some sort of logic that combines testing if an expression has a certain type or structure, and then conditionally extracting components of its state for further processing. For example, all Java programmers are familiar with the instanceof-and-cast idiom:
几乎每个程序都包含某种逻辑,结合了对表达式的类型或结构的测试,然后有条件地提取其中的状态组件以进行进一步处理。例如,所有Java程序员都熟悉“先instanceof再转换”的习惯用法:
if (obj instanceof String) {
String s = (String) obj;
// use s
}
if (obj instanceof String) {
String s = (String) obj;
// 使用s
}
There are three things going on here: a test (is obj
a String
?), a conversion (casting obj
to String
), and the declaration of a new local variable (s
) so we can use the string value. This pattern is straightforward and understood by all Java programmers, but is suboptimal for several reasons. It is tedious; doing both the type test and cast should be unnecessary (what else would you do after an instanceof
test?). This boilerplate -- in particular, the three occurrences of the type String
--- obfuscates the more significant logic that follows. But most importantly, the repetition provides opportunities for errors to creep unnoticed into programs.
这里发生了三件事情:一个测试(obj
是不是一个String
),一个转换(将obj
转换为String
),和定义一个新的局部变量(s
)以便我们可以使用字符串的值。这种模式很简单,并且所有Java程序员都可以理解,但是由于一些原因,这不是最优的。这很乏味:应该没有必要既做类型测试,同时又做类型转换(你还能在instanceof
测试之后做什么其他的呢?)。这些样板代码——特别是出现了三次的String
类型——混淆了后面更重要的逻辑。但最重要的是,重复代码为错误提供了机会且不易被察觉。
Rather than reach for ad-hoc solutions, we believe it is time for Java to embrace pattern matching. Pattern matching allows the desired 'shape' of an object to be expressed concisely (the pattern), and for various statements and expressions to test that 'shape' against their input (the matching). Many languages, from Haskell to C#, have embraced pattern matching for its brevity and safety.
与寻求特定的解决方案相比,我们相信是时候让Java拥抱模式匹配了。模式匹配允许简洁地表达对象所需的“形态”(模式),并允许各种语句和表达式针对其输入来测试“形态”(匹配)。从Hashkell到C#,许多语言都出于其简洁性和安全性而拥抱了模式匹配。
A pattern is a combination of (1) a predicate that can be applied to a target, and (2) a set of binding variables that are extracted from the target only if the predicate successfully applies to it.
模式是二者的组合:(1)可以应用于目标的谓词;(2)仅在谓词成功应用于目标时才从目标中提取的一组绑定变量。
A type test pattern consists of a predicate that specifies a type, along with a single binding variable.
类型测试模式由指定类型的谓词和单个绑定变量组合。
The instanceof
operator (JLS 15.20.2) is extended to take a type test pattern instead of just a type. In the code below, the phrase String s
is the type test pattern:
扩展instanceof
运算符(JLS 15.20.2)以采用类型测试模式,而不仅仅是类型。在下面的代码中,短语String s
就是类型测试模式:
if (obj instanceof String s) {
// can use s here
} else {
// can't use s here
}
if (obj instanceof String s) {
// 这里可以使用s
} else {
// 这里不能使用s
}
The instanceof
operator "matches" the target obj
to the type test pattern as follows: if obj
is an instance of String
, then it is cast to String
and assigned to the binding variable s
. The binding variable is in scope in the true block of the if
statement, and not in the false block of the if
statement.
instanceof
运算符将目标obj
与类型测试模式相“匹配”:如果obj
是String
的实例,那就将其转换为String
并赋值给绑定变量s
。绑定变量的作用域是if
语句的true代码块,而不是if
语句的false代码块。
The scope of a binding variable, unlike the scope of a local variable, is determined by the semantics of the containing expressions and statements. For example, in this code:
与局部变量的作用域不同,绑定变量的作用域由包含的表达式和语句的语义确定。例如,在这样的代码中:
if (!(obj instanceof String s)) {
.. s.contains(..) ..
} else {
.. s.contains(..) ..
}
if (!(obj instanceof String s)) {
.. s.contains(..) ..
} else {
.. s.contains(..) ..
}
the s
in the true block refers to a field in the enclosing class, and the s
in the false block refers to the binding variable introduced by the instanceof
operator.
true代码块中的s
引用封闭类中的字段,false代码块中的s
引用由instanceof
运算符引入的绑定变量。
When the conditional of the if
statement grows more complicated than a single instanceof
, the scope of the binding variable grows accordingly. For example, in this code:
当if
语句的条件变得比单个instanceof
更复杂时,绑定变量的范围也会相应地增长。例如,在这样的代码中:
if (obj instanceof String s && s.length() > 5) {.. s.contains(..) ..}
if (obj instanceof String s && s.length() > 5) {.. s.contains(..) ..}
the binding variable s
is in scope on the right hand side of the &&
operator, as well as in the true block. (The right hand side is only evaluated if instanceof
succeeded and assigned to s
.) On the other hand, in this code:
绑定变量s
的作用域既是&&
运算符的右边范围,同时也是true代码块范围。(右边范围只会在instanceof
成功时运算并赋值给s
。)另外,在这样的代码中:
if (obj instanceof String s || s.length() > 5) {.. s.contains(..) ..}
if (obj instanceof String s || s.length() > 5) {.. s.contains(..) ..}
the binding variable s
is not in scope on the right hand side of the ||
operator, nor is it in scope in the true block. (s
at these points refers to a field in the enclosing class.)
绑定变量s
的作用域既不是code>||运算符的右边范围,同时也不是true代码块范围。(此例中的s
引用封闭类型中的字段。)
There are no changes to how instanceof
works when the target is null. That is, the pattern will only match, and s
will only be assigned, if obj
is not null.
当目标是null时instanceof
的工作方式不变。即,只有obj
不是null时,模式才会匹配,s
才会被赋值。
The use of pattern matching in instanceof
should dramatically reduce the overall number of explicit casts in Java programs. Moreover, type test patterns are particularly useful when writing equality methods. Consider the following equality method taken from Item 10 of the Effective Java book:
在instanceof
中使用模式匹配应该会大大减少Java中显式强制转换的总数。此外,类型测试模式在编写相等方法时特别有用。考虑下面选择Effective Java一书第10条的相等方法:
@Override public boolean equals(Object o) {
return (o instanceof CaseInsensitiveString) &&
((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}
@Override public boolean equals(Object o) {
return (o instanceof CaseInsensitiveString) &&
((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}
Using a type test pattern means it can be rewritten to the clearer:
使用类型测试模式意味着这可以重新写成更清楚的样子:
@Override public boolean equals(Object o) {
return (o instanceof CaseInsensitiveString cis) &&
cis.s.equalsIgnoreCase(s);
}
@Override public boolean equals(Object o) {
return (o instanceof CaseInsensitiveString cis) &&
cis.s.equalsIgnoreCase(s);
}
RelationalExpression:
...
RelationalExpression instanceof
ReferenceType
RelationalExpression instanceof
Pattern
关系表达式:
...
关系表达式 instanceof
引用类型
关系表达式 instanceof
模式
Future JEPs will enhance the Java programming language with pattern matching for other language constructs, such as switch
expressions and statements.
未来的JEP将通过与其他语言结构,如switch
表达式和语句,进行模式匹配来增强Java编程语言。
The benefits of type-test patterns could be obtained by flow typing in if
statements, or by a type switch construct. Pattern matching generalizes both of these constructs.
类型测试模式的好处可以通过在if
语句的流式键入或类型switch结构中获得。模式匹配涵盖了这两种结构。
The implementation may make use of JEP 309 (Dynamic Class-File Constants).
实现可能用到JEP 309(动态Class文件常量)。