案例一:

short s = 1;

s = s + 1;

上述代码能否通过编译,为什么?

案例二:

short s = 1;

s += 1;

上述代码能否通过编译,为什么?

以上两个问题是非常经典的一道Java面试题,面试中出现的频率在70%以上。答案可能大家都非常清楚了,案例一可以不能通过编译,案例二可以,那么这又是为什么呢?

答案要从运算符的优先级、运算机制、默认数据类型和类型转换的机制中来寻找。

首先,我们来分析“ s = s + 1; ”。在这个表达式中,涉及到了加法(+)和赋值(=)两种运算。加法运算的优先级高于赋值运算,因此会先编译加法运算。在这个过程中,加号左侧为 short 类型的变量 s,右侧为常量值 1,1的默认数据类型为 int 类型,这种情况下,s 会自动类型提升,隐式转换为 int 类型。这个过程结束之后,会继续对赋值运算进行编译。此时,等号左侧为 short 类型变量 s,等号右侧为 int 类型变量,要把 int 类型变量的值赋给 short 类型变量,由于 int 类型的数据宽长为 32 位,short 类型的数据长度为16位,而变量的值在编译期间是无法确定的,所以编译器会认为在这个赋值过程中会发生数据信息丢失,从而编译不能通过。

我们再来看一些情况:

byte a = 3; // 编译正确

byte b = 1000; // 编译出错 Type mismatch: cannot convert from int to byte

float c = .7; // 编译出错 Type mismatch: cannot convert from double to float

在这个例子中,我们会有这样的疑问,同样是由 int 类型常量赋给 byte 类型变量,为什么 a = 3 可以通过,而 b = 1000 却不能通过。这是因为,对于常量,编译器是可以确定其值是否在目标类型的数值范围之内,3在 byte 类型的范围之内,因此转换后不会有数据信息丢失,编译成功,而1000超出了 byte 的数值范围,转换会造成数据信息丢失,转换失败。而 float c = .7,.7为 double 类型的常量,double 类型的精度高于 float 类型,如果从 double 转换为 float 则会产生精度的损失,所以编译不通过。(注意:double d = .7; float f = .7f; 这里,d 大于 f。大家可以通过程序验证一下)。

接下来,我们再来看第二个案例。这个案例中,只涉及到一个复合赋值“ += ”。复合赋值 E1 op= E2 等价于简单赋值 E1 =(T)((E1)op(E2)),其中 T 是 E1 的类型,除非 E1 只被计算一次。也就是说,复合赋值表达式自动地将它们所执行的计算的结果转型为其左侧变量的类型。如果结果的类型与该变量的类型相同,那么这个转型不会造成任何影响。然而,如果结果的类型比该变量的类型要宽,那么复合赋值操作符将悄悄地执行一个窄化原始类型转换。所以,s += 1; 先编译加法运算,再编译强制类型转换,最后编译赋值运算,这样,运算符左右两侧数据类型一致,编译通过。

补充点小知识,我们通过对字节码文件进行反编译,得到其对应的 JVM 指令,从 JVM 指令是否一致,就可以判断出两种操作的实质是否一样。首先来看源码一:

public class Demo {

public static void main(String[] args) {

short s = 1;

s += 1;

}

}

运行 javap -c -verbose Demo.class,得到结果一如下:

Classfile /C:/Users/Administrator/Desktop/Demo.class

Last modified 2018年7月20日; size 268 bytes

MD5 checksum 88b70724a8593e4946d538b0460c5bc1

Compiled from "Demo.java"

public class Demo

minor version: 0

major version: 54

flags: (0x0021) ACC_PUBLIC, ACC_SUPER

this_class: #2 // Demo

super_class: #3 // java/lang/Object

interfaces: 0, fields: 0, methods: 2, attributes: 1

Constant pool:

#1 = Methodref #3.#12 // java/lang/Object."":()V

#2 = Class #13 // Demo

#3 = Class #14 // java/lang/Object

#4 = Utf8 #5 = Utf8 ()V

#6 = Utf8 Code

#7 = Utf8 LineNumberTable

#8 = Utf8 main

#9 = Utf8 ([Ljava/lang/String;)V

#10 = Utf8 SourceFile

#11 = Utf8 Demo.java

#12 = NameAndType #4:#5 // "":()V

#13 = Utf8 Demo

#14 = Utf8 java/lang/Object

{

public Demo();

descriptor: ()V

flags: (0x0001) ACC_PUBLIC

Code:

stack=1, locals=1, args_size=1

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

LineNumberTable:

line 3: 0

public static void main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)V

flags: (0x0009) ACC_PUBLIC, ACC_STATIC

Code:

stack=2, locals=2, args_size=1

0: iconst_1

1: istore_1

2: iload_1

3: iconst_1

4: iadd

5: i2s

6: istore_1

7: return

LineNumberTable:

line 5: 0

line 6: 2

line 7: 7

}

SourceFile: "Demo.java"

再来看另一段源码二:

public class Demo {

public static void main(String[] args) {

short s = 1;

s = (short) (s + 1);

}

}

运行 javap -c -verbose Demo.class,得到结果二如下:

Classfile /C:/Users/Administrator/Desktop/Demo.class

Last modified 2018年7月20日; size 288 bytes

MD5 checksum 1100ccec295a1315d82752f3af1e9300

Compiled from "Demo.java"

public class com.cml.springcloud.Demo

minor version: 0

major version: 54

flags: (0x0021) ACC_PUBLIC, ACC_SUPER

this_class: #2 // com/cml/springcloud/Demo

super_class: #3 // java/lang/Object

interfaces: 0, fields: 0, methods: 2, attributes: 1

Constant pool:

#1 = Methodref #3.#12 // java/lang/Object."":()V

#2 = Class #13 // com/cml/springcloud/Demo

#3 = Class #14 // java/lang/Object

#4 = Utf8 #5 = Utf8 ()V

#6 = Utf8 Code

#7 = Utf8 LineNumberTable

#8 = Utf8 main

#9 = Utf8 ([Ljava/lang/String;)V

#10 = Utf8 SourceFile

#11 = Utf8 Demo.java

#12 = NameAndType #4:#5 // "":()V

#13 = Utf8 com/cml/springcloud/Demo

#14 = Utf8 java/lang/Object

{

public com.cml.springcloud.Demo();

descriptor: ()V

flags: (0x0001) ACC_PUBLIC

Code:

stack=1, locals=1, args_size=1

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

LineNumberTable:

line 3: 0

public static void main(java.lang.String[]);

descriptor: ([Ljava/lang/String;)V

flags: (0x0009) ACC_PUBLIC, ACC_STATIC

Code:

stack=2, locals=2, args_size=1

0: iconst_1

1: istore_1

2: iload_1

3: iconst_1

4: iadd

5: i2s

6: istore_1

7: return

LineNumberTable:

line 5: 0

line 6: 2

line 7: 7

}

SourceFile: "Demo.java"

从得到的结果,我们可以看出,其对应的 JVM 指令是一致的,由此可以判定这两种表达式是等价的。

视频教程参考:Java视频教程合集

如果此博文对您由帮助,就打赏一下吧。您的支持,是我坚持的动力。

标题

java short s=s 1_Java 面试题 short s = 1; s = s + 1; 与 s += 1; 背后的秘密相关推荐

  1. Java知识点汇总以及常见面试题

    Java知识点汇总以及常见面试题 1. "=="和equals()的区别 2. 构造方法能不能重写或者重载 3. 基本数据类型 4. 匿名内部类能被继承? 5. Integer和i ...

  2. 【Java面试宝典】1000+面试题附答案详解,最全面详细

    进大厂是大部分程序员的梦想,而进大厂的门槛也是比较高的,所以这里整理了一份阿里.美团.滴滴.头条等大厂面试大全,其中概括的知识点有:Java.MyBatis.ZooKeeper.Dubbo.Elast ...

  3. 最新Java面试八股文,1000+面试题答案详解全面看完拿下大厂offer

    进大厂是大部分程序员的梦想,而进大厂的门槛也是比较高的,所以这里整理了一份阿里.美团.滴滴.头条等大厂面试大全,其中概括的知识点有:Java.MyBatis.ZooKeeper.Dubbo.Elast ...

  4. 2021年JAVA 精心整理的常见面试题-附详细答案【持续更新~~】

    先罗列本篇文章包含的Java 常见面试的主题: 一.Java基础面试题 二.Java 集合框架 三.Linux常用指令 四.MySQL基础面试 多线程与多进程面试 常见设计模式 JVM 底层 关注我们 ...

  5. 开发c s架构java应用程序6_java常见面试题

    1.什么是B/S架构?什么是C/S架构B/S(Browser/Server), 浏览器/服务器程序C/S(Client/Server),客户端/服务端,桌面应用程序 2.你所知道网络协议有那些? HT ...

  6. JAVA常见且基础的面试题

    1.什么是B/S架构?什么是C/S架构 B/S(Browser/Server),浏览器/服务器程序 C/S(Client/Server),客户端/服务端,桌面应用程序 2.你所知道网络协议有那些? H ...

  7. Java并发编程71道面试题及答案

    Java并发编程71道面试题及答案 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方 ...

  8. Java 最常见的 10000+ 面试题及答案整理:持续更新

    Java面试题以及答案整理[最新版]Java高级面试题大全(2021版),发现网上很多Java面试题都没有答案,所以花了很长时间搜集,本套Java面试题大全,汇总了大量经典的Java程序员面试题以及答 ...

  9. java cglib jar包_Java面试题|反射必看的4道面试题

    上三篇: 动力节点:Java面试题|多线程21道必看面试题​zhuanlan.zhihu.com 动力节点:面试题|Java基础17道常见面试题​zhuanlan.zhihu.com 动力节点:面试题 ...

最新文章

  1. Java 三位数的变形
  2. 134. Leetcode 136. 只出现一次的数字 (位运算-只出现一次的数字相关题目)
  3. 用qmlscene进行原型制作
  4. 使用python自己搭建一个简单的BP神经网络
  5. 【转】Dicom文件解析!!!!!!
  6. Unity3D基础21:UI简介
  7. STM32 HAL SPI读取MPU6500的设备ID异常
  8. 资源工具分享(第1期):后端架构师技术图谱
  9. 从网络启动恢复RG750Gr3
  10. 基于RGMII的FPGA千兆以太网设计
  11. 【项目技术点总结之二】微信小程序中集成antvF2进行图表开发
  12. 北卡州立大学计算机科学硕士,北卡罗莱纳州立大学计算机科学专业研究生申请条件有哪些?...
  13. String format格式化
  14. Cabbage教学(5)——条件体
  15. 图片怎么压缩到100k?照片怎么压缩到指定大小
  16. 求职材料准备-入门导读
  17. k均值聚类算法考试例题_k means聚类算法实例
  18. 2022年湖北助理工程师职称评审费用是多少?多久出证呢?甘建二
  19. Voicemeeter - PC混音器
  20. Linux基础中的基础 一

热门文章

  1. mysql 函数定义常量_php如何定义一个自定义常量
  2. 查看二进制文件,报错 You are not using binary logging
  3. 自定义http报头_浅谈http协议(三):HTTP 报文及其结构
  4. 多目标进化优化 郑金华pdf_简化审批流程 金华首张以“告知承诺制”审批的医疗器械经营许可证发放...
  5. Oracle中开启并行和相关查询
  6. JavaSE----代码块、内部类
  7. 计算机应用基础离线考核,东师2016年秋季《计算机应用基础》期末考核离线作业...
  8. java如何初始化对象_java中对象的初始化过程
  9. linux内核实现片选跳变,《Linux内核设计与实现》读书笔记:进程调度
  10. java的环境变量_java学习册|JDK|环境变量