class Test{
int p = (p=1) + p; // ERR "Cannot reference a field before it is defined"
int q = (q=1) + this.q; //fine!
void f() {
int t = (t=1) + t; // fine!
}
}
在第一种情况下,我理解为:何时分配(或后续添加?)执行时,p被视为未声明。
但是为什么在一种方法中它是不同的呢?OK t不会被视为未初始化,因为(t=1)是在添加之前执行的。好的,t不是一个字段,但它现在也没有声明!
我能理解吗?要不我就记住这个区别?
也许这也与此有关:
static int x = Test.x + (x=1) + Test.x; // produces 2
void f() {
int y = y + (y=1) + y; // ERR local variable y may not have been initialized
}
为什么是2?第一个(x=1)以某种方式计算(x未声明!!!),然后返回1,现在x已经赋值了(!?)并且包含1,所以这两个测试。x为1,但(x=1)运算符也返回1,因此结果应为1,并且作为评估测试的结果,3应(重新分配)到x中。x(x=1)试验。x
表达式。
部分回答:事实上,结果是具体实施的。JLS只保证二元运算符的操作数求值顺序(从左到右)。但是,如果我们有具有相同优先级的二元运算符(比如,加号),它们的求值顺序就不能得到保证。在我的例子中,加号操作符的求值顺序是最左边的,这就是为什么静态“intx=Test.x(ZERO)(x=1)Test.x(x=1之后是1”)是0 1 1(请记住,x=1是返回赋值的运算符)。在我的例子中,方法“inty=y(y=1)y最左边的加号运算符首先求值(给出错误),但如果JVM选择首先求值第二个加号运算符,则保证首先求值其左操作数,(y=1)将使y变量初始化(因此代码将编译!)
我仍然不确定为什么(x=1)不被视为未声明的字段。我依稀记得,JLS允许未声明的变量在LHS(所以任何赋值工作),但不在RHS(x, int sth=x)。我可以用下面的片段记住它:
class Test {
{ x = 7; } // fine! Initializer is like a regular method
int x;
static { y = 7; } // fine! Initializer is like a regular method
static int y;
另外,这肯定不是Java中默认值和初始化的重复-没有直接的解释。在这里,我们不仅需要默认值(int为零)规则,还需要在一个非常复杂的组合中使用许多不同的规则(运算符优先级,特别是一些罕见的赋值特性!)。我还知道这里的赋值优先级最低,赋值是一个运算符,它返回值!
也许我不会说得很详细,但我会尝试一下,您指出了Java中变量生命周期的非常好的例子。
int p = (p=1) + p; // ERR "Cannot reference a field before it is defined"
在这种情况下,p
是一个类字段,当编译器加载的类p尚未初始化时(类的第一次扫描,因此p尚未加载到内存中,无法计算)。
void f() {
int t = (t=1) + t; // fine!
}
在这种情况下,编译器只加载函数的定义,而不管函数内部是什么(我的意思是,如果没有语法错误,并且没有任何类型的错误,每个IDE都可以检查这一点)。这可能是一个奇怪的声明,但很好,在调用函数并初始化t inline之前,不会对其进行计算。
static int x = Test.x + (x=1) + Test.x; // produces 2
在这种情况下x
是一个静态变量,静态的东西是在类之前加载的,所以你可以想象你的编译器把x
字段放在你写的上面。在这一行中,你说x等于1,所以1 1=2。这就像做这样的事
static int x = 1;
x = Test.x + Test.x;
阅读Java语言规范中局部变量声明的范围。您的确切问题在示例6.3-2中描述。描述是这样的:
以下程序导致编译时错误,因为局部变量p
的初始化在局部变量p
声明的范围内,但局部变量p
还没有值,无法使用。
问题内容: 在以下情况中,使用以下命令在第一次调用中成功,但是在第二次调用中失败: 为什么会这样,并且有一种方法可以在方法上设置属性,使其仅存在于一个实例上,而不是针对类的每个实例? Python 3.2.2 问题答案: 简短的答案:无法将自定义属性添加到绑定方法。 长答案如下。 在Python中,有 函数对象 和 方法对象 。当定义一个类时,该语句创建一个 函数对象 ,该 对象 位于该类的名称空
描述 (Description) 字符类[\p{L}&&[^\p{Lu}]]匹配除大写字母之外的任何字符。 例子 (Example) 以下示例显示了Unicode字符类匹配的用法。 package com.wenjiangs; import java.util.regex.Matcher; import java.util.regex.Pattern; public class UnicodeCh
这是代码: 编译器(gcc)警告外部减法处的整数溢出: 在我的机器上获得了正确的结果1。 为什么? 这是因为指针地址是无符号整数,但ptrdiff_t是有符号整数,无法处理这些大数字吗? 我看到了 和 不要造成溢出。 我正在努力了解这里的幕后情况。这是我关于stackoverflow的第一个问题,如果我的问题可以改进,请告诉我。
我正在试图理解是什么意思。即使我将其删除,该表达式的工作原理也是一样的,即: 我知道我可以用引用匹配的模式。是什么?
本文向大家介绍C中的++ * p,* p ++和* ++ p之间的区别,包括了C中的++ * p,* p ++和* ++ p之间的区别的使用技巧和注意事项,需要的朋友参考一下 指针式 在C语言中,* p表示存储在指针中的值。++是前缀和后缀表达式中使用的增量运算符。*是取消引用运算符。前缀++和*的优先级相同,并且两者从右到左关联。后缀++的优先级高于前缀++和*,并且从左到右具有关联性。请参见以
.我的理解是,这是因为javac像解释器一样工作,逐行读取。但是当涉及到我们调用类中的字段并向其传递值的方法时,我们可以在方法声明之后定义字段。 参数eyes、tail、Teath和coat在用于将值传递给构造函数后定义。javac如何理解方法后有一个变量。允许这样做是因为我们只能定义字段,而不能在类定义中对它们进行任何操作吗?