Java坑人面试题系列: 变量声明(中级难度)

2023-11-17

作用域规则与变量覆盖面试题

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 变量声明与作用域》 一节中对变量声明的作用域范围做了详细说明。

有两个需要着重强调的点:

  1. 方法参数的作用域范围: 形参的作用域范围,是方法,构造函数或lambda表达式对应的body。
  2. for循环初始化语句中声明的局部变量, 作用域范围包括: 初始化部分、初始化后面的条件判断部分,递增更新语句,以及循环体中的语句。

通过我们的分析可知,正确选项为: B, C, E.

相关链接

原文链接: https://blogs.oracle.com/javamagazine/quiz-yourself-variable-declaration-intermediate

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java坑人面试题系列: 变量声明(中级难度) 的相关文章

随机推荐

  • SpeedTree导入Unity解决方案

    微软的Note笔记 和网页编辑不能很好复制 这里没有图 建议查看另一个链接 https onenote com webapp pages token KxEyAkijcfJZgzOF30PAPkVySHIcjsPyhrE5wkJoK9KTI
  • 计算机必知必会:进程process与线程thread

    进程和线程这对概念的理解也是很难的 至今网络上可查的资料对其的理解出入都挺大 在不同的操作系统中 如linux和windows中 其概念和实现都是有出入的 因此 我在这里结合我自己的理解谈下这两个概念 讲的都是一般性的概念 并且主要是基以W
  • pandas报错:columns overlap but no suffix specified

    使用pandas的join连接两张表 例如表1是left 表2是right 这两张表都有共同的字段user name 我就以user name这个字段连接这两张表 left join right how left on user name
  • 2018.09.29 学习笔记 // 前端Javascript // 日期、Math、数组与对象API

    题目 答案见后面 获取2018 09 29格式的日期 获取随机数 要求是长度一直的字符串格式 写一个能遍历对象的数组的通用forEach函数 日期和Math var a Date now 获取当前时间毫秒数 从1970年到现在走了多少毫秒
  • 使用Matlab实现基于计算机视觉的DIP芯片缺陷检测系统附带GUI界面

    使用Matlab实现基于计算机视觉的DIP芯片缺陷检测系统附带GUI界面 计算机视觉在工业生产中的应用越来越广泛 其中一项重要的应用是对芯片制造过程中的缺陷进行检测 本文将介绍如何使用Matlab实现一个基于计算机视觉的DIP芯片缺陷检测系
  • pythonnone赋值-【零基础学Python】def语句,参数和None值

    像之前的print input 和len 功能 Python提供了一些类似的内置函数 另外也可以自己编写自定义函数 示例 def hello print Howdy print Howdy print Hello there hello 第
  • 刷脸支付商户流水不断服务商收益不断

    刷脸支付的管道红利 刷脸支付是获利的其实刷脸支付的商业模式本质上也是一种管道收入 通过一家商户的流水得到佣金 十家商户 N家商户 开通刷脸支付的商户越多 佣金就越多 可以赚取的收益也就越多 就正如管道一样 只要商家在营业 那么你的收入就源源
  • 初识数据库-mysql

    初识数据库 不同的数据库 sql语句不一样 总体大致差不多 数据存储的简短回顾 在内存中临时存储数据所需 变量 数组 长度不可变 类型太单一 对象 对象数组 近乎解决了数组类型太单一的问题 集合 解决了数组长度不可变 持久存储数据 I O
  • 应用层协议 --- DNS协议

    DNS Domain Name Service 域名服务 DNS协议基于UDP 使用端口号53 由数字组成的 IP 地址很难记忆 所以我们上网使用网站 IP 地址的别名 域名 实际使用中 域名与 IP 地址是对应的 这种对应关系保存在DNS
  • 【前端面经】JS-如何使用 JavaScript 来判断用户设备类型?

    在 Web 开发中 有时需要针对不同的设备类型进行不同的处理 例如 对于移动设备 我们可能需要采用不同的布局或者交互方式 以提供更好的用户体验 因此 如何判断用户设备类型成为了一个重要的问题 1 使用 navigator userAgent
  • python优雅地爬虫

    申明 仅用作学习用途 不提供任何的商业价值 背景 我需要获得新闻 然后tts 在每天上班的路上可以听一下 具体的方案后期我也会做一次分享 先看我喜欢的万能的老路 获得html内容 gt python的工具库解析 获得元素中的内容 完成 好家
  • 『Newsletter丨第一期』PieCloudDB 新增自动启停、预聚集、试用规则优化、费用中心等多项功能模块...

    第一部分 PieCloudDB 最新动态 PieCloudDB 完成多个产品兼容性认证 PieCloudDB 与多家基础架构软件厂商完成产品兼容性认证 类别包括操作系统 服务器 CPU 云平台 新增 8 家生态伙伴 包括龙蜥 麒麟 中科可控
  • c语言求fibonacci数列前20,求fibonacci数列的前20个数之和

    使用数组求Fibonacci数列的前20项 要求4项一行输出 斐波那契数列通项公式 斐波那契数列指的是这样一个数列 1 1 2 3 5 8 13 21 这个数列从第三项开始 每一项都等于前两项之和 includeintmain inta 2
  • 容斥原理——经典例题(组合数学)

    一 容斥原理 就是人们为了不重复计算重叠部分 想出的一种不重复计算的方法 先来认识一下这两个符号 与 如图 蓝色的圈就是c1c2 红色的圈围起来的就是c1c2 二 例题 组合数学 1 题目 1 1 题目描述 八是个很有趣的数字啊 八 发 八
  • Centos nginx配置文档

    1 安装nginx yum install nginx 2 Nginx常用命令 查看版本 nginx v 启动 nginx c etc nginx nginx conf 重新加载配置 nginx s reload 停止 nginx s st
  • Bat批处理使用ren批量重命名文件,比如批量去掉文件名称的前4位

    从手机下导入一批照片到电脑 照片开头都是以IMG 开头 甚是烦 使用ren可以批量去掉IMG 开头的几个字符 参考如下 去掉文件名称的最前面4位 去掉文件名称的最后5位 去掉的5位包括 jpg这四个后缀 echo off Deep Lee
  • OCR文字检测主要算法

    转载 https www mayi888 com archives 60604 文字检测是文字识别过程中的一个非常重要的环节 文字检测的主要目标是将图片中的文字区域位置检测出来 以便于进行后面的文字识别 只有找到了文本所在区域 才能对其内容
  • 西门子 PLC S7单边通信

    PLC通信 1 组态 编程 1 打开博途软件 创建新项目 命名为 通信 2 添加新设备 命名为A 这里选择的是CPU1211C 版本V4 2 3 CPU属性设置 启用系统存储器字节和时钟存储器字节 4 以太网地址设置 IP地址设为 192
  • 一文说明白SMC继电器的三种模式:迟滞模式,窗口模式,报警模式

    阅读时间5分钟 有不少同学表示 不理解迟滞模式 窗口模式 报警模式 这里花点儿时间说明一下 这三种模式按照难易程度 1 报警模式 这种方式顾名思义 到压力报警 回到正常范围 报警消除 简单易懂 不过 如果我们需要的压力是0 7MPa 那么我
  • Java坑人面试题系列: 变量声明(中级难度)

    作用域规则与变量覆盖面试题 Java Magazine上面有一个专门坑人的面试题系列 https blogs oracle com javamagazine quiz 2 这些问题的设计宗旨 主要是测试面试者对Java语言的了解程度 而不是