在Java8 编译器中,JCVariableDecl 中的nameexpr 字段是什么
In Java 8 compiler, what is nameexpr field in JCVariableDecl for
在java编译器JCTree.java
中,JCVariableDecl
定义如下:
public static class JCVariableDecl extends JCStatement implements VariableTree {
/** variable modifiers */
public JCModifiers mods;
/** variable name */
public Name name;
/** variable name expression */
public JCExpression nameexpr;
/** type of the variable */
public JCExpression vartype;
/** variable's initial value */
public JCExpression init;
/** symbol */
public VarSymbol sym;
...
}
但是,我不确定 nameexpr
在这里有什么用。什么情况下nameexpr
字段不为空?我已经阅读了 Java 8 和 JavacParser.java
的 BNF
JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
int pos = token.pos;
Name name;
if (lambdaParameter && token.kind == UNDERSCORE) {
log.error(pos, "underscore.as.identifier.in.lambda");
name = token.name();
nextToken();
} else {
if (allowThisIdent) {
JCExpression pn = qualident(false);
if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) {
name = ((JCIdent)pn).name;
} else {
if ((mods.flags & Flags.VARARGS) != 0) {
log.error(token.pos, "varargs.and.receiver");
}
if (token.kind == LBRACKET) {
log.error(token.pos, "array.and.receiver");
}
return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
}
} else {
name = ident();
}
}
if ((mods.flags & Flags.VARARGS) != 0 &&
token.kind == LBRACKET) {
log.error(token.pos, "varargs.and.old.array.syntax");
}
type = bracketsOpt(type);
return toP(F.at(pos).VarDef(mods, name, type, null));
}
看来我们需要构造一个案例来制作
pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this
为假。
代码正在检查接收器参数,如下所示:
public class SomeClass {
public void foo(SomeClass this) {
// ^^^^^^^^^^^^^^
}
}
在spec的语法产生式规则中,列为:
FormalParameterList:
ReceiverParameter
FormalParameters , LastFormalParameter
LastFormalParameter
FormalParameters:
FormalParameter {, FormalParameter}
ReceiverParameter {, FormalParameter}
ReceiverParameter:
{Annotation} UnannType [Identifier .] this
这是一个名称为“this”的参数,如果在内部 class 构造函数中,则为 NameOfOuterClass.this
。 this
不是标识符,所以这就是它检查 pn.hasTag(Tag.IDENT)
.
的原因
如果您之前没有听说过接收者参数,它基本上是一个“一种可选的句法设备,其存在的唯一目的是允许在源代码中表示所表示对象的类型,以便可以对该类型进行注释,”并且“它永远不会绑定到作为方法调用表达式或合格的 class 实例创建表达式中的参数传递的任何值,并且它在 运行 时间没有任何影响”,正如语言规范所说的那样。
由于它与变量声明符的结构几乎相同,我猜他们决定也使用 JCVariableDecl
来表示它。
在java编译器JCTree.java
中,JCVariableDecl
定义如下:
public static class JCVariableDecl extends JCStatement implements VariableTree {
/** variable modifiers */
public JCModifiers mods;
/** variable name */
public Name name;
/** variable name expression */
public JCExpression nameexpr;
/** type of the variable */
public JCExpression vartype;
/** variable's initial value */
public JCExpression init;
/** symbol */
public VarSymbol sym;
...
}
但是,我不确定 nameexpr
在这里有什么用。什么情况下nameexpr
字段不为空?我已经阅读了 Java 8 和 JavacParser.java
JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
int pos = token.pos;
Name name;
if (lambdaParameter && token.kind == UNDERSCORE) {
log.error(pos, "underscore.as.identifier.in.lambda");
name = token.name();
nextToken();
} else {
if (allowThisIdent) {
JCExpression pn = qualident(false);
if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) {
name = ((JCIdent)pn).name;
} else {
if ((mods.flags & Flags.VARARGS) != 0) {
log.error(token.pos, "varargs.and.receiver");
}
if (token.kind == LBRACKET) {
log.error(token.pos, "array.and.receiver");
}
return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
}
} else {
name = ident();
}
}
if ((mods.flags & Flags.VARARGS) != 0 &&
token.kind == LBRACKET) {
log.error(token.pos, "varargs.and.old.array.syntax");
}
type = bracketsOpt(type);
return toP(F.at(pos).VarDef(mods, name, type, null));
}
看来我们需要构造一个案例来制作
pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this
为假。
代码正在检查接收器参数,如下所示:
public class SomeClass {
public void foo(SomeClass this) {
// ^^^^^^^^^^^^^^
}
}
在spec的语法产生式规则中,列为:
FormalParameterList:
ReceiverParameter
FormalParameters , LastFormalParameter
LastFormalParameter
FormalParameters:
FormalParameter {, FormalParameter}
ReceiverParameter {, FormalParameter}
ReceiverParameter:
{Annotation} UnannType [Identifier .] this
这是一个名称为“this”的参数,如果在内部 class 构造函数中,则为 NameOfOuterClass.this
。 this
不是标识符,所以这就是它检查 pn.hasTag(Tag.IDENT)
.
如果您之前没有听说过接收者参数,它基本上是一个“一种可选的句法设备,其存在的唯一目的是允许在源代码中表示所表示对象的类型,以便可以对该类型进行注释,”并且“它永远不会绑定到作为方法调用表达式或合格的 class 实例创建表达式中的参数传递的任何值,并且它在 运行 时间没有任何影响”,正如语言规范所说的那样。
由于它与变量声明符的结构几乎相同,我猜他们决定也使用 JCVariableDecl
来表示它。