`
tianlihu
  • 浏览: 311882 次
  • 性别: Icon_minigender_1
  • 来自: 石家庄
社区版块
存档分类
最新评论

关于基本类型的简单赋值运算和复合赋值运算

阅读更多
本文版权归作者所有,仅供用来网上学习来用,读者可以收藏,请不要下载到本机或重新发布到其它网站

有一道很经典的面试题是这样的:
short s1 = 1; s1 = s1 + 1; 有什么错? short s1 = 1; s1 += 1;有错吗?

答案很简单:
1. 编译出错。类型不匹配,需要强制类型转换。
2. 没有错误。

有一朋友说不是太明白这是为什么。我在这里分析一下原因。
对于前半部分:
short s1 = 1; s1 = s1 + 1;

   在java语言规范里,如果表达式中, 当对中间值的精确要求有时可能会超过任何一个操作数的范围, JVM会临时自动提升这个操作数的类型。
    像我们这个题目的前面部分,s1 + 1, 我们把类型写出来s1(short) + 1(int)这时JVM会自动把s1先提升成int,然后再跟后面的1(int)相加,这样就是int + int的运算了。但是为什么会有编译错误呢?因为int + int的结果还是int。我们看一下这个例子:
short s1 = 1;
Object result = s1 + 1;
System.out.println(result.getClass().getSimpleName());

结果是:
Integer

从结果可以看出,结果是int的包装类Integer。所以s1 + 1的结果是int类型的。因此把s1 + 1重新赋值给s1,即s1 = s1 + 1,会丢失精度,编译出错。

对于后半部分 s1 += 1,个人认为可以分为两部分,见下面代码:
short s1 = 1;
s1 = (short)((int) s1 + 1);

这样解释的原因可以再看下面的例子:
public class Test {
	public void test1(){
		short s1 = 1;
		s1 = (short)((int) s1 + 1);
	}
	
	public void test2() {
		short s1 = 1;
		s1 += 1;
	}
}

查看Test.class文件的字节码文件:
 public void test1();
    0  iconst_1
    1  istore_1 [s1]
    2  iload_1 [s1]
    3  iconst_1
    4  iadd
    5  i2s
    6  istore_1 [s1]
    7  return
      Line numbers:
        [pc: 0, line: 4]
        [pc: 2, line: 5]
        [pc: 7, line: 6]
      Local variable table:
        [pc: 0, pc: 8] local: this index: 0 type: Test
        [pc: 2, pc: 8] local: s1 index: 1 type: short
  
  public void test2();
    0  iconst_1
    1  istore_1 [s1]
    2  iload_1 [s1]
    3  iconst_1
    4  iadd
    5  i2s
    6  istore_1 [s1]
    7  return
      Line numbers:
        [pc: 0, line: 9]
        [pc: 2, line: 10]
        [pc: 7, line: 11]
      Local variable table:
        [pc: 0, pc: 8] local: this index: 0 type: Test
        [pc: 2, pc: 8] local: s1 index: 1 type: short

    除了11-13行和28-30行的内的行号不同之外,其余部分都一样。即这两上写法其实是等效的。
    s1 = (short)((int) s1 + 1);  可以简化为s1 = (short)(s1 + 1);因为从short到int JVM会自动提升类型。

    最后补充一点,JVM会自动提升类型的表达式为:
short +|-|*|/|% short = (int) short +|-|*|/|% (int) short;
byte  +|-|*|/|% byte  = (int) byte  +|-|*|/|% (int) byte;
char  +|-|*|/|% char  = (int) char  +|-|*|/|% (int) char;

   因为这些类型的运算很容易就会越界。它们之间的任意组合都会先转换成int,然后再运算,结果为int类型。但是遇到更高精度的操作数,如float、double,它们也会向float、double自动提升类型。自动提升类型除基本赋值外,都是向精度高的方向进行的。
   对于short、byte、char的基本赋值,就像short s1 = 1;是int类型自动降低类型到short的。
  
0
0
分享到:
评论
4 楼 hitjava 2009-05-13  
不过只查看的话,可以用反射来看变量的类型。但是运算中的详细转换情况还是不能知道。
3 楼 hitjava 2009-05-13  
tianlihu 写道

hitjava 写道
想问下,有没有不用查看class的其它办法,如何确定s1 += 1后s1的类型 我暂时没有办法,因为这个属于JDK底层的实现,s1 += 1这个表达式不能拆开,我也尝试过,没有成功,因为生成的字节码不一样,不能说明问题

现在想来,只简单去想,s1本来就是short,最后赋值给s1时,它没有理由去变成另外一个类型

而且s1+1也只是在运算时使用了一个转换后的值。s1本身并没有变。

谢谢楼主啊
2 楼 tianlihu 2009-05-11  
hitjava 写道

想问下,有没有不用查看class的其它办法,如何确定s1 += 1后s1的类型

我暂时没有办法,因为这个属于JDK底层的实现,s1 += 1这个表达式不能拆开,我也尝试过,没有成功,因为生成的字节码不一样,不能说明问题
1 楼 hitjava 2009-05-10  
想问下,有没有不用查看class的其它办法,如何确定s1 += 1后s1的类型

相关推荐

    Pascal程序设计 实验报告

    4. Pascal的复合数据类型:枚举、子界、数组和记录类型 5. 程序设计内容如下:使用记录数组来记录一个班学生的信息。学生信息包括:姓名、性别、年龄、民族(汉、蒙、满)、总成绩。输入一个班每人的信息,按照总...

    词法分析器

    用EBNF范式设计的一个简单的程序设计语言(语言中有+、-运算,语句有赋值语句、输入语句、输出语句、复合语句)

    华中科技大学 编译原理 面向过程的C语言的编译器设计 含有词法分析和语法分析、语义分析、中间代码生成的 源码.zip

    源语言要求至少包含的语言成分如下: 数据类型至少包括char类型、int类型和float类型 基本运算至少包括算术运算、比较运算、自增自减运算和复合赋值运算 控制语句至少包括if语句和while语句 实验内容:完整可运行的...

    Python程序基础:Python中的运算符.pptx

    赋值运算符用来给变量赋值,Python提供的赋值运算符可分为简单赋值与复合赋值两大类。;关系运算符又称比较运算符,用于比较运算符两侧的值,比较的结果是一个布尔值,即True或False。;Python的逻辑运算符包括and(与...

    C语言程序设计教学大纲.pdf

    然后,课程将深入探讨基本数据类型和运算,包括标识符、常量与变量的概念、基本数据类型中的整型、单精度实型、双精度实型、字符型常量和变量的定义与使用方法、算术运算符和算术表达式、赋值运算符和赋值表达式、...

    2013年全国计算机等级考试二级(c++)考纲

    * 熟练掌握C++表达式类型及求值规则(赋值运算、算术运算符和算术表达式、关系运算符和关系表达式、逻辑运算符和逻辑表达式、条件运算、指针运算、逗号表达式) 三、 C++的基本语句 * 掌握C++的基本语句,例如赋值...

    C语言程序设计标准教程

    在本章中,我们先介绍基本数据类型中的整型、浮点型和字符型。其余类型在以后各章中陆续介绍。  对于基本数据类型量,按其取值是否可改变又分为常量和变量两种。在程序执行过程中,其值不发生改变的量称为常量,...

    visual c++考试大纲

    4.C表达式类型(赋值表达式、算术表达式、关系表达式、逻辑表达式、条件表达式、逗号表达式)和求值规则。   (三)基本语句 1.表达式语句,空语句,复合语句。 2.数据的输入与输出,输入输出函数的调用。 3.复合...

    C++程序设计-谭浩强-清晰版完整书签

    C++程序设计-谭浩强-清晰版完整书签 封面 -24 目录 -10 第1篇 基本知识 1 第1章 C++的初步知识 3 1.1 从C到C++ 3 ... 2.6.3 复合的赋值运算符 38 2.6.4 赋值表达式 39 2.7 逗号运算符与逗号表达式 40 习题 41

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    10.8 有关指针的数据类型和指针运算的小结 167 10.8.1 有关指针的数据类型的小结 167 10.8.2 指针运算的小结 167 10.8.3 void 指针类型 168 11 结构体与共用体 11.1 定义一个结构的一般形式 170 11.2 结构类型变量的...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    10.8 有关指针的数据类型和指针运算的小结 167 10.8.1 有关指针的数据类型的小结 167 10.8.2 指针运算的小结 167 10.8.3 void 指针类型 168 11 结构体与共用体 11.1 定义一个结构的一般形式 170 11.2 结构类型变量的...

    广东计算机水平考试二级《C++程序设计》考试大纲及样题

    广东计算机水平考试二级《C++程序设计》考试大纲及样题 本考试大纲旨在考察学生对C++语言程序设计的基本知识和应用能力。考试内容涵盖了C++语言的基本...编程题分简单操作题、简单应用题和综合应用题3种类型的考题。

    C++和面向对象数值计算

    2.3.3 复合赋值语句 2.3.4 增值减值语句 2.3.5 复合语句 2.3.6 条件语句 2.3.7 循环语句 2.4 斐波纳契数 2.5 练习 第3章派生类型 3.1 常量和宏 3.2 枚举类型 3.3 数组 3.4 结构 3.5 ...

    全国高等学校计算机水平考试Ⅱ级―《C++程序设计》考试大纲(试行)

    * 掌握 C++的自动类型转换和强制类型转换 主要考点: * 数据类型的种类 * 不同类型数据间的转换与运算 * 运算符的种类 * 运算符优先级和结合性 ㈡ 基本语句 * 了解 C 语句的概念及种类 * 掌握 C 语言常用的输入/...

    09年二级C语言考试大纲

    4.C表达式类型(赋值表达式,算术表达式,关系表达式,逻辑表达式,条件表达式,逗号表达式)和求值规则。 三、基本语句 1.表达式语句,空语句,复合语句。 2.输入输出函数的调用,正确输入数据并正确设计...

    二级c未来教育题库破解及资源

    4.C表达式类型(赋值表达式,算术表达式,关系表达式,逻辑表达式,条件表达式,逗号表达式)和求值规则。  三、基本语句 1.表达式语句,空语句,复合语句。 2.输入输出函数的调用,正确输入数据并正确设计...

    狂人C程序员入门必备

    1.2.2 最简单的C语言程序的基本结构 1.2.3 Dev C++ 1.3 printf()函数初步 1.3.1 简单的一般用法 1.3.2 特殊的字符 1.4 C语言的“字母”和“单词” 1.4.1 C语言的字母 1.4 12C语言的“词” 小结 概念与术语 风格与...

    编译原理简易C编译器

    1. 基本要求 1数据类型:int,char 2语句:赋值(=),if,while,for;赋值 循环 条件判断 3算术运算:+,-,*,/,%,++,--,&,|,^,~,,>> 4关系运算:==,>,<,>=,,!= 5逻辑运算:&&(与),||(或),!...

    新手必看编程法则C++

    第4章表达式和基本语句 4.1 运算符的优先级 4.2 复合表达式 4.3 if 语句 4.4 循环语句的效率 4.5 for 语句的循环控制变量 4.6 switch语句 4.7 goto语句 第5章常量 5.1 为什么需要常量 5.2 const 与 #define的比较 ...

Global site tag (gtag.js) - Google Analytics