Java坑人面试题系列: 变量声明(中级难度)
Posted 铁锚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java坑人面试题系列: 变量声明(中级难度)相关的知识,希望对你有一定的参考价值。
作用域规则与变量覆盖面试题
Java Magazine上面有一个专门坑人的面试题系列: https://blogs.oracle.com/javamagazine/quiz-2。
这些问题的设计宗旨,主要是测试面试者对Java语言的了解程度,而不是为了用弯弯绕绕的手段把面试者搞蒙。
如果你看过往期的问题,就会发现每一个都不简单。
这些试题模拟了认证考试中的一些难题。 而 “中级(intermediate)” 和 “高级(advanced)” 指的是试题难度,而不是说这些知识本身很深。 一般来说,“高级”问题会稍微难一点。
问题(中级难度)
下面哪些代码是正确的写法?
- A.
class C1
void foo(int a)
for (int a = 0; a < 5; a++)
- B.
class C2
int a = 0;
int a = 1;
- C.
class C3
int a = 0;
int a = 1;
- D.
class C4
int a = 0;
for (int a = 0; a < 5; a++)
- E.
class C5
for (int a = 0; a < 5; a++)
int a = 0;
到底是哪些选项正确呢? 请先思考,再看下面的解答。
答案和解析
这道题主要考察变量的作用域以及优先级:同一作用域下如果存在两个相同的变量名称(标识符),那么会简单会指向一个变量而忽略另一个。
一般来说,局部变量会覆盖同名的类属性和实例属性,但方法作用域内的局部变量则不允许覆盖。
在编写程序代码时,一般规范都会要求明确指定类名或者 this
来引用对应的字段。
下面是一个简单的使用示例:
public class MyClass
static int x = 99;
int y = 100;
public static void showX()
int x = 9;
System.out.println("x is " + x); // x is 9
System.out.println("MyClass.x is " + MyClass.x); // MyClass.x is 99
public void showY()
int y = 10;
System.out.println("y is " + y); // y is 10
System.out.println("this.y is " + this.y); // this.y is 100
接下来依次解读试题中给出的选项。
先看选项 A
,
class C1
void foo(int a)
for (int a = 0; a < 5; a++)
可以看到有一个变量 a
作为方法参数。
方法参数也是局部变量,其作用域范围从参数列表开始,一直到方法结束。
在方法内部的for
循环中,也声明了一个名为 a
的局部变量。
因此,根据规则,在某个作用域范围内,不允许存在多个同名的局部变量
, 所以这段代码无法编译, 选项A不正确
。
选项 B
,
class C2
int a = 0;
int a = 1;
类中定义了实例变量 a
,在初始化语句块中又定义了一个局部变量a
,类似于方法代码中的局部变量声明。
所以在初始化块的作用域范围内, 局部变量覆盖了实例属性。
这段代码可以正确编译并运行, 所以 选项B正确
。
选项 C
的内容如下,
class C3
int a = 0;
int a = 1;
在两个单独的初始块中, 都声明了局部变量a
, 但各自的作用域范围都被限制为代码块之中, 所以不会发生重叠,也就没有变量冲突。
当然,这段代码没什么实际的作用,因为在初始化块中声明的变量,在其他地方都不可看,在语句块执行完成后会被丢弃。
可能有些同学会觉得编译器会报错,但实际上这些代码块都是会执行的,并没有不可达代码。
既然语法没问题, 那么 选项C正确
。
看选项 D
,
class C4
int a = 0;
for (int a = 0; a < 5; a++)
代码块中先是声明了一个局部变量, 然后for
循环中又声明了同名的变量。
因为for循环中声明的局部变量,作用域范围从声明处开始,直到循环结束。
也就是说, 在循环体范围内,存在两个同名的局部变量,这是违反语法规定的。
跟选项 A
中的情况有点类似,区别只在于选项 A
中声明的是方法参数,而选项D中声明的是普通局部变量。
由此可知, 选项D不正确
。
最后看选项 E
,
class C5
for (int a = 0; a < 5; a++)
int a = 0;
和选项D
看起来有点像, 但这次是循环先声明自己的局部变量,循环结束后,后面的代码接着声明了一个同名的普通局部变量。
这两个局部变量的作用域并不重叠,也不冲突,所以代码有效,选项E正确
。
小结
在 《Java语言规范 - 6.3 变量声明与作用域》 一节中对变量声明的作用域范围做了详细说明。
有两个需要着重强调的点:
- 方法参数的作用域范围: 形参的作用域范围,是方法,构造函数或lambda表达式对应的body。
for
循环初始化语句中声明的局部变量, 作用域范围包括: 初始化部分、初始化后面的条件判断部分,递增更新语句,以及循环体中的语句。
通过我们的分析可知,正确选项为: B
, C
, E
.
相关链接
- Java坑人面试题系列: 包装类(中级难度)
- Java坑人面试题系列: 比对while与for循环(中级)
- Java坑人面试题系列: 集合(高级)
- Java坑人面试题系列: 线程/线程池(高级)
- Java坑人面试题系列: 变量声明(中级)
原文链接: https://blogs.oracle.com/javamagazine/quiz-yourself-variable-declaration-intermediate
以上是关于Java坑人面试题系列: 变量声明(中级难度)的主要内容,如果未能解决你的问题,请参考以下文章