`
tianlihu
  • 浏览: 314002 次
  • 性别: 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的类型

相关推荐

    计算机二级C语言考点09赋值运算及复合赋值运算.pdf

    本资源涵盖了C语言中赋值运算和复合赋值运算的知识点,包括赋值语句的格式、赋值运算符、复合赋值运算符、变量的定义和赋值、表达式的计算顺序等。 一、赋值语句 赋值语句是将一个值赋给变量的语句。基本格式为:...

    基于数据类型结构观点的C语言中赋值运算教学方法.pdf

    其中,赋值运算符是C语言中使用最频繁的运算符之一,涉及简单赋值、复合算数赋值以及复合位运算赋值等三种类型共11种具体的赋值运算。然而,由于C语言的赋值运算与数据类型紧密相关,对初学者而言,复杂数据类型赋值...

    3.2赋值运算1

    总结起来,赋值运算在C++中扮演着核心角色,它涉及到变量的初始化、值的传递和类型转换。理解赋值运算符的工作原理、优先级、结合性以及隐式类型转换,对于编写高效、正确的C++代码至关重要。在实际编程中,熟练掌握...

    程序设计-赋值运算.pptx

    除了基本的赋值运算符,还有复合赋值运算符,如 `+=`、`-=`、`*=`、`/=`、`%=`、`>>=`、`、`&=`、`|=` 和 `^=`。这些运算符可以同时进行算术运算和赋值,例如 `a += 7 + 5` 等同于 `a = a + (7 + 5)`,这将增加 `a` ...

    Swift教程:基本操作符 赋值和算术运算及取余

    总结,这个教程将通过视频形式详细讲解Swift中的基本赋值和算术运算,以及取余操作。理解并熟练运用这些操作符是编写高效且正确Swift代码的基础。通过观看视频,开发者可以更直观地掌握这些概念,并在实践中应用。

    C语言中《赋值运算》.docx

    C语言中《赋值运算》详解 在C语言中,赋值运算符是一种基本的运算符,它可以将右边表达式的结果赋值给左边的变量。赋值运算符有多种形式,包括基本的赋值运算符、复合赋值运算符、自增自减运算符等。 复合赋值...

    第二章基本数据类型和运算[参考].pdf

    10. 赋值运算:复合赋值运算符如+=,-=,*=,/=等,如b=a+1相当于b=a; b=b+1。 综上所述,本章主要介绍了C语言中的基本数据类型,如字符型、整型、浮点型,以及相关的运算规则、常数的表示方式、运算符的优先级和...

    C语言中《赋值运算》[参照].pdf

    然而,C语言还提供了复合赋值运算符,这些运算符结合了算术运算和赋值操作,使得代码更加简洁。复合赋值运算符包括: 1. 加赋值运算符“+=”:例如,`a += 3+1`等同于`a = a + (3+1)`,会先计算右侧的表达式,然后...

    C语言 数据类型 赋值 运算符 算法.pdf

    复合赋值运算符可以简化代码,提高编译效率和代码质量。 七、逗号运算符和逗号表达式 逗号运算符是将多个表达式连接成一个表达式的运算符。逗号表达式是使用逗号运算符连接的多个表达式。例如`a = 1, b = 2, c = 3...

    Java变量与数据类型、数据运算中易混知识点总结

    变量可以看作是程序中存储数据的容器,它有特定的名称(标识符)和类型。在Java中,声明变量时需要指定其类型,例如`int age;`,这里的`age`是变量名,`int`是变量的数据类型,表示`age`可以存储整数。变量必须先...

    基本数据类型和运算宣贯.pdf

    从所提供的文件内容来看,这段文字似乎是一份关于编程中基本数据类型和运算的宣贯材料。虽然因为OCR扫描的原因,文档中存在一些识别错误,但我们可以从中提炼出一些编程语言中常见数据类型和运算符的知识点。 数据...

    (完整word)C语言练习题—基本数据类型和运算.pdf

    '这样的复合赋值运算会按照从右到左的顺序执行,先进行乘法,再进行减法,最后进行加法。 以上只是部分知识点的解析,实际题目中还有更多关于运算符、数据类型的练习,这些都是学习C语言的基础。通过这些练习,可以...

    python学习记录(数值运算与赋值快捷方式)

    赋值快捷方式(或称为复合赋值操作符)是一种简化代码的方法,可以更高效地进行数值运算并重新赋值。例如,在原始代码示例中: ```python a = 2 b = 3 a = a * 3 # 等价于 a *= 3 b *= 3 # 等价于 b = b * 3 print...

    C语言程序设计基本数据类型及运算PPT课件.pptx

    C语言中的数据类型分为基本类型和复合类型两大类。本节主要关注基本类型,包括整型、实型、字符型和空类型。 ##### 2.1 整型数据 整型数据用来表示整数,根据其长度和符号的不同可以细分为以下几种: 1. **基本...

    C语言练习题基本数据类型和运算[文].pdf

    在学习C语言时,理解和熟练运用基本数据类型和运算至关重要。以下是基于题目中提到的知识点进行的详细解释: 1. **基本数据类型**:C语言中的基本数据类型包括整型(int)、字符型(char)、浮点型(float)和双精度浮点...

    基本运算写法.docx

    再者,善用自加、自减指令和复合赋值运算可以提高代码质量。例如,使用a-=1或a+=1等表达式,大多数编译器会生成单条inc或dec指令,而a=a+1或a=a-1可能会生成更长的指令序列。对于AVR单片机上的编译器,如ICCAVR、...

    C程序设计:第二章 数据类型及基本运算.ppt

    在C语言中,数据类型大致可以分为基本类型、枚举类型、指针类型和复合类型。 1. 基本数据类型: - `char`:用于存储单个字符,如字母、数字或特殊符号。在计算机内存中,通常占1字节(8位)。 - `int`:用于存储...

    [大学生考试专用C语言教学课件]第3章 基本算术运算.pptx

    本资源是一个关于C语言的教学课件,第3章主要讲述基本算术运算。该课件适合大学生学习C语言的需要,内容详细、系统、全面,是大学生考试的必备良品。 在本章中,我们首先了解了为什么需要学习运算符,因为计算机的...

    MATLAB数据及其运算_matlab运算实例源码.ppt

    MATLAB数据及其运算_matlab运算实例源码 MATLAB数据及其运算是MATLAB编程语言的基本...MATLAB数据及其运算是MATLAB编程语言的基本组成部分,了解MATLAB数据的特点、表示方法和基本运算是掌握MATLAB编程语言的基础。

    C高级语言程序设计:03算术运算与逻辑运算.pptx

    算术运算符用于执行基本的数学运算,如加法、减法、乘法、除法和取模运算。 - **加法运算符(+)**:用于进行数值相加或表示正数。例如:`3 + 5`、`+3`。 - **减法运算符(-)**:用于进行数值相减或表示负数。例如...

Global site tag (gtag.js) - Google Analytics