昨天提到了一个奇怪的现象:
byte num = 128;
如上撰写,你的IDE将会在128底下亮出红线,并说:「Type mismatch: cannot convert from int to byte」
今天就会来探讨一下为什麽会发生这个奇怪的现象,不过在进入正题之前,想先谈谈何谓字面常量(literal constant)
昨天谈到了基本型别(primitive type),其实被宣告为基本型别的变数所储存的值就是各种字面常量,字面常量本身就代表了最纯粹的数值,没有经过记忆体位址的包装,1就是1,2就是2。不过字面常量就只有我们日常生活使用的十进位(decimal)数字吗?当然不止,还有十六进位(hexadecimal)、八进位(octet)、二进位(binary):
以上这些都是可以在Java程序中表达的字面常量,而且也都等於我们所谓的10这个数值。
欸,那还有一个字元(char)勒? 它是怎麽被储存的? 电脑真的会存进abcd吗?
实际上在Java,字元骨子里是一个16 bits范围的正数值,每个数值会再透过转换转成我们所看到的文字,所以当我们如下指派时:
int num = 'A';
num会变成65的int数值(JLS5.1.2),神奇吧。所以字元就像是一个萝卜一个坑,每个数字会代表一个文字,再查表对应出代表的文字(Unicode Table)
最後提点一下,昨天虽然有提到String字串不是基本型别,可是你应该有注意到我们指派给String型别变数的也是像字面常量的值,其实没错!我们在等号右边给它的字串也是一种字面常量,但字串比较特别一点,之後有机会再讨论。
好了,该进入正题了~ 到底为什麽JVM要说我们给byte变数一个int字面常量勒?
答案就是,就是这样...没有为什麽,这就是Java在字面常量上的潜规则,只要我们直接打出数字的数值,它预设就是int的型态。而之所以byte num = 127会可以编译成功是因为Java有自动针对byte, short, char, int常数narrowing conversion的功能(JLS5.2)
整数的常量会自动视为int型态,浮点数呢? 浮点数则是自动视为double型态,所以以下会编译不过哦:
float fNum = 1.5;
可是我就是想要存1.5到float型别的变数怎麽办? 这时候就有2种办法了:
float fNum01 = 1.5f;
float fNum02 = (float)1.5;
第一种办法是从字面常量下手,如果我们希望表示出float型态的浮点数,就得在最後面加上一个"f";
第二种办法是使用Java的转型(cast)语法,在值的前面用括号包住我们想转成的型别名称,就可以强制转过去了。这个转型水也是有点深度...之後可能需要花点篇幅说明,因为并不是可以无脑转型的,尤其之後又有非基本型别的状况时。
其实在整数也会有这样的情况,由於数字预设是int型别,那如果我们写下了一个超出int型别范围的数值,并预计用一个long型别的变数来装,要怎麽做到勒? 答案就是:
long num = 2147483648L;
在整数数值的最後面加上"L",就会把常量转换为long型态了。
好了,我们只剩最後一个部分要讲了,就是运算时常量的潜规则。
byte n1 = 1;
byte n2 = 2;
byte n3 = n1 + n2;
以上程序码在第三行会出错,诡异吧。这是因为Java预设在进行运算时,若运算元是小於int的型别,会先自动转化为int型别後,再进行运算。所以只要有加减乘除的运算,最後结果一定最小会是int的型别!那下面的话呢:
int n1 = 1;
long n2 = 2;
int n3 = n1 + n2;
这样的话第三行也还是最出错,因为现在最大的型别变成long了,这时Java会先把所有型别都提升到long,再进行运算。这种特性称为自动提升(promote)。
最後来个逗趣的东西:
int nn = 1 + 'A';
试试看nn会等於多少吧。
这篇有点长,来做个小结:
天啊我把Java讲得好复杂哈哈,而且根本还没进到物件@@
Angular [目标] 启动程序先导入Login元件 1. 新增元件、模组 Syntax:ng h...
前言 现在到了练习NumPy的最後一天,现在要开始跟资料分析的流程接轨 所以我决定从网路上的开源资...
我们昨天有提到说,Django是一个Python的框架,理所当然的我们的电脑也要有Python才能运...
Ruby on Rails 是使用Ruby这套开放原始码(采用MIT授权)、 物件导向程序语言所开发...
协定的语法其实算是大量的使用在结构与类别中,尤其需要更底层的作用的时候,协定算是提供了一个共识,让程...