java基础深入解析基本类型
一、基本类型的简介
基本类型的两条准则:
Java中,如果对整数不指定类型,默认时int类型,对小数不指定类型,默认是double类型。
基本类型由小到大,可以自动转换,但是由大到小,则需要强制类型转换。所占的字节数:
byte: 1个字节;
char: 2个字节;
short: 2个字节;
int: 4个字节;
long: 8个字节;
float: 4个字节;(6位小数,指数是:10^-38~10^38; 范围:)
double: 8个字节;
char:Java中用 \u四位十六进制的数字 (即使在注释中出现\u,后面如果
跟的不是4个16进制的数字,也会报错)表示将字符转换成对应的unicode编 码;也可以用字符来赋值如: char c=\u0000 ,char的默认初始化值,unicode的null字符
基本类型的后缀:
long : l 或 L
float: f 或 F;
double: d 或 D
二、类型转换
正如前面所说的,类型由大到小,是必需强制转换。但这并不意味着需要用户手动强制转换 —— 也就是 隐式转换。隐式转换 说的透彻点就是由编译器来进行强制转换,不需要用户再去写强制转换的代码。下面的前两个小点所说的便是特殊的隐式类型转换。
本小节所讨论的类型转换是不包括 类型由小到大的转换,讨论的是其他比较容易让人迷惑的类型转换
1. int类型的字面常量转换成比int类型低的变量类型
所谓的字面常量就是值的本身,如 5、7、“aa”等等。我们先看个例子:
publicstaticvoidmain(String[]args){inta=8;//8是字面常量byteb=9;//9是字面常量charc=9+5;//常量表达式shorts=(short)(c+10);//变量表达式,需要显式强制转换}
上面的代码是经过编译的,是正确的。b是byte类型,但b=9不需要显式地手动强制转换,这是因为9是字面常量,是由JVM自动完成。
我们再来看一下c=9+5,c是char类型,9+5得到结果是int类型,但也不需要显式地手动强制转换。这是因为 9+5是常量表达式,所以在编译期间已经由编译器计算出结果了,即经过编译后,相当于 c=14,也是字面常量,所以可以隐式转换。同理,short s = (short) (c+10);子所以不能隐式转换,就是因为表达式不是常量表达式,包含了变量,只能在运行期间完成,所以就要手动强制转换。
×××字面常量隐式转换的限制:
×××字面常量的大小超出目标类型所能表示的范围时,要手动强制类型转换。byteb=128;//编译错误,128超出byte类型所能表示的范围bytec=(byte)128;//编译通过
对于传参数时,必须要显式地进行强制类型转换,明确转换的类型编译器子所以这样要求,其实为了避免 方法重载出现的隐式转换 与 小类型自动转大类型 发生冲突。
publicstaticvoidmain(String[]args){shortMethod(8);//编译错误shortMethod((short)8);//编译通过longMethod(8);//编译通过,因为这是小类型变成大类型,是不需要强制类型转换的}publicstaticvoidshortMethod(shortc){System.out.println(c);}publicstaticvoidlongMethod(shortl){System.out.println(l);}
char类型的特殊情况 :下面再细讲2. 复合运算符的隐式转换
*复合运算符(+=、-=、=、/=、%=)是可以将右边表达式的类型自动强制转换成左边的类型**
publicstaticvoidmain(String[]args){inta=8;shorts=5;s+=a;s+=a+5;}
s+=a、s+=a+5;的表达式计算结果都是int类型,但都不需要手动强制转换。其实,如果是反编译这段代码的class文件,你会发现s+=a;,其实是被编译器处理成了
s=(short)(s+a)
也就是说对于所有的复合运算的隐式类型转换,其实是编译器自动添加类型转换的代码。
所以,相对于×××字面常量的隐式转换,复合运算符的隐式转换则没有任何限制因为前者只能在编译器期间发生,后者则是编译器实实在在的补全了类型转换的代码。
3. 特殊的char类型
char类型在基本类中是一个比较特殊的存在。这种特殊性在于char类型是一个无符号类型,所以char类型与其他基本类型不是子集与父集间的关系(其他类型都是有符号的类型)。也就是说,char类型与byte、short之间的转换都需要显式的强制类型转换(小类型自动转换成大类型失败)。
同时,由于char类型是一个无符号类型,所以对于×××字面常量的隐式转换的限制,不仅包括字面常量数值的大小不能超出2个字节,还包括字面常量数值不能为负数
byteb=2;charc=2;//编译通过c=100000000000;//编译不通过,超出char类型的范围chard=-2//字面常量为负数,编译不通过d=(char)-100;//编译通过charf=(char)b;//编译通过,必须显式的强制类型转换f=b;//编译不通过,不能隐式转换inti=c;//编译通过,可以不需要强制类型转换shorts=(short)c;//编译通过,必须显式地强制类型转换
char类型是无符号的类型,这种无符号也体现在在其转换成int类型时,也就是说,char类型在扩展时,也是按无符号的方式扩展,扩展位填0。我们来看一个例子:
publicstaticvoidmain(String[]args){shorts=-5;charc=(char)s;System.out.println(c==s);//falseSystem.out.println((int)c=+(int)c);//转换成int类型,值为65531System.out.println((short)c=+(short)c);//-5System.out.println((int)s=+(int)s);//-5}
运行结果:
false
(int)c = 65531
(short)c = -5
(int)s = -5
从上面的结果发现,char类型的c 与 short类s其实存储字节码内容是一样的,但由于前者是无符号,所以扩展成int类型的结果是 65531,而不是 -5。运算符==比较的就是他们扩展成int类型的值,所以为fasle。
对char类型的类型转换,可以总结成以下几点:
char类型与byte、short的相互转换,都需要显式地强类型制转换。
对于数值是负数的,都需要进行显式地强制类型转换,特别是在×××字面常量的隐式转换中。
char类型转换成int、long类型是符合 小类型转大类型的规则,即无需要强制类型转换。4. 运算结果的类型
在Java中,一个运算结果的类型是与表达式中类型最高的相等,如:
charcc=5;floatdd=0.6f+cc;//最高类型是float,运算结果是floatfloatee=(float)(0.6d+cc);//最高类型是double,运算结果也是doubleintaa=5+cc;//最高类型是int,运算结果也为int
但是,对于最高类型是byte、short、char的运算来说,则运行结果却不是最高类型,而是int类型。看下面的例子,c、d运算的最高类型都是char,但运算结果却是int,所以需要强制类型转换。
byteb=2;chara=5;charc=(char)(a+b);//byte+char,运算结果的类型为int,需要强制类型转换inte=a+b;//编译通过,不需要强制类型转换,可以证明是intchard=(char)(a+c);//char+char,shorts1=5;shorts2=6;shorts3=(short)s1+s2;
综上所述,java的运算结果的类型有两个性质:
运算结果的类型必须是int类型或int类型以上。
最高类型低于int类型的,运算结果都为int类型。否则,运算结果与表达式中最高类型一致。三、浮点数类型
1. 浮点类型的介绍
我们都知道,long类型转换成float类型是不需要强制类型转换的,也就是说相对于flaot类型,long类型是小类型,存储的范围要更小。然而flaot只占了4个字节,而long却占了8个字节,long类型的存储空间要比float类型大。这究竟是怎么一回事,我们接下来将细细分析。
浮点数使用 IEEE(电气和电子工程师协会)格式。 浮点数类型使用 符号位、指数、有效位数(尾数)来表示。要注意一下,尾数的最高
在java中,float 和 double 的结构如下:
类 型符 号 位指 数 域有效位域
float1位8位23位
double1位11位52位
符号位:0为正,1为负;
指数域:无符号的,float的偏移量为127(即float的指数范围是-126~127,),double
有效位域:无符号的;
2. 浮点类型的两个需要注意的地方
1)存储的小数的数值可能是模糊值
publicstaticvoidmain(String[]args){doubled1=0.1;doubled2=0.2;System.out.println(d1+d2==0.3);System.out.println(d1+d2);}
运行结果:
false
0.30000000000000004
上述的运算结果并不是错误。这是因为无法用二进制来准确地存储的0.3,这是一个无限循环的值,与10进制的1/3很相似。不只是0.3,很多小数都是无法准确地用浮点型表示,其实这是由 小数的十进制转成二进制的算法所决定的,十进制的小数要不断乘2,知道最后的结果为整数才是最后的二进制值,但这有可能怎么也得不到整数,所以最后得到的结果可能是一个 无限值 ,浮点型就无法表示了
但是对于 整数 来说,在浮点数的有效范围内,则都是精确的。同样,也是由于转换算法:十进制的整数转成二进制的算法是不断对2求余数,所以 不会存在无限值的情况;
2)浮点数的有效位及精度
浮点型所能表示的有效位是有限的,所以哪怕是整数,只要超出有效位数,也只能存储相似值,也就是该数值的最低有效位将会丢失,从而造精度丢失。
float类型的二进制有效位是24位,对应十进制的7 ~ 8位数字;double类型的二进制53位,对应十进制的10 ~ 11位数字。
double、float类型 所能表示的范围比int、long类型表示的范围要广,也浮点类型属于大类型。但是,并不能完美地表×××,浮点类型的精度丢失会造成一些问题。
publicstaticvoidmain(String[]args){inta=3000000;intb=30000000;floatf1=a;floatf2=b;System.out.println(3000000==3000001+(f1==f1+1));System.out.println(30000000==30000001+(f2==f2+1));System.out.println(3000000的有效二进制位数:+Integer.toBinaryString(a).length());System.out.println(30000000的有效二进制位数:+Integer.toBinaryString(b).length());}
运行结果:
3000000 == 3000001 false
30000000 == 30000001 true
3000000的有效二进制位数: 22
30000000的有效二进制位数: 25
上面的例子很好体现了精度丢失所带来的后果:30000000==30000001的比较居然为true了。而造成这种结果的原因就是 30000000的有效二进制位数是25位,超出了float所能表示的有效位24位,最后一位就被舍去,所以就造成在刚加的1也被舍去,因此30000000的加一操作前后的浮点型表示是一样的。
当然,并不是超出浮点型的有效位就不能精确表示,其实,主要看的是最高有效位与最低非0有效位之间的 “间隙”,如果间隙的在浮点型的有效位数内,自然可以精确表示,因为舍去的低有效位都是0,自然就无所谓了。如果上面的例子的浮点型用的是double就不会丢失精度了,因为double的精度是52位。
3)解决浮点型精度丢失的问题
浮点型带来精度丢失的问题是很让人头痛的,所以一般情况下,在程序中是不会使用float、double来存储比较大的数据。而商业计算往往要求结果精确。《Effactive Java》书中有一句话:
float和double类型的主要设计目标是为了科学计算和工程计算
JDK为此提供了两个高精度的大数操作类给我们:BigInteger、BigDecimal。
java基础深入解析基本类型的更多相关文章
- java 基础知识二 基本类型与运算符
java 基础知识二 基本类型与运算符 1.标识符 定义:为类.方法.变量起的名称 由大小写字母.数字.下划线(_)和美元符号($)组成,同时不能以数字开头 2.关键字 java语言保留特殊含义或者 ...
- Java基础教程:枚举类型
Java基础教程:枚举类型 枚举类型 枚举是将一具有类似特性的值归纳在一起的方法.比如,我们可以将周一到周日设计为一个枚举类型.彩虹的七种颜色设计为一个枚举类型. 常量实现枚举 我们通过定义常量的方式 ...
- java基础-8种基本类型
正文 java中的八种基础类型. boolean:只有两个值,false,true 带符号类型 byte:占用1个字节,一个字节也就是8位,那么由于是最高一位是用来表示 负还是正,所以范围就是 -2^ ...
- Java基础教程(15)--枚举类型
枚举类型定义了一个枚举值的列表,每个值是一个标识符.例如,下面的语句声明了一个枚举类型,用来表示星期的可能情况: public enum Day { SUNDAY, MONDAY, TUESDAY ...
- python基础——python解析yaml类型文件
一.yaml介绍 yaml全称Yet Another Markup Language(另一种标记语言).采用yaml作为配置文件,文件看起来直观.简洁.方便理解.yaml文件可以解析字典.列表和一些基 ...
- java基础讲解04-----数据类型和运算符
1.java的基本数据类型 1.数值型 { 整数型 byte , short ,int ,long 浮点型 float , double } 2.字符型 3.布尔型 2.运算符 1.赋 ...
- JAVA基础——异常--解析
简介 异常处理是java语言的重要特性之一,<Three Rules for effective Exception Handling>一文中是这么解释的:它主要帮助我们在debug的 ...
- Java基础 ----- 判断对象的类型
1. 判断对象的类型:instanceOf 和 isInstance 或者直接将对象强转给任意一个类型,如果转换成功,则可以确定,如果不成功,在异常提示中可以确定类型 public static vo ...
- ## Java基础(二):变量类型
Java 变量类型 一.局部变量:类的方法中的变量 局部变量声明在方法.构造方法或者语句块中: 局部变量在方法.构造方语句块中被执行的时候创建,当他们执行完成后,变量被销毁 访问修饰符不能用于局部变量 ...
随机推荐
- 在Keras模型中one-hot编码,Embedding层,使用预训练的词向量/处理图片
最近看了吴恩达老师的深度学习课程,又看了python深度学习这本书,对深度学习有了大概的了解,但是在实战的时候, 还是会有一些细枝末节没有完全弄懂,这篇文章就用来总结一下用keras实现深度学习算法的 ...
- c++四种强制类型转化
c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast C++ 类型转换(C风格的强制转换): (1)将浮点型数据赋值给整型变 ...
- 定时器事件QtimerEvent 随机数 qrand Qtimer定时器
QTimerEvent类:定时器事件.QObject的子类都可使用 int QObject::startTimer(int interval)[参数:毫秒][返回值:定时器整型编号]来开启一个定时器 ...
- mysql buffer
php与mysql的连接有三种方式,mysql,mysqli,pdo.不管使用哪种方式进行连接,都有使用buffer和不使用buffer的区别. 什么叫使用buffer和不使用buffer呢? 客户端 ...
- Perl实战(一)
在Perl中,我们可以通过uc,lc,\U,\L来修改变量的值.其中uc,\U可以将变量中的字母全部转换为大写. lc,\L可以将变量中的字母全部转换为小写. $big = "\U$var& ...
- php抛出异常
php抛出异常:throw new Exception("xxxxxx!"); 实例代码: try{ if ($mysqli->connect_errno) { sleep( ...
- C/C++之内存对齐
数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍.DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽.X86 CPU能直接访问对齐的数据,当它试图访问一个未对齐的数据 ...
- P2322 [HNOI2006]最短母串问题
P2322 [HNOI2006]最短母串问题 AC自动机+bfs 题目要求:在AC自动机建的Trie图上找到一条最短链,包含所有带结尾标记的点 因为n<12,所以我们可以用二进制保存状态:某个带 ...
- Python3 pip出现Fatal error in launcher: Unable to create process using '"'
Python3 pip出现Fatal error in launcher: Unable to create process using '"' 问题分析: 先python2又安装了pyth ...
- 企业应用开发中最常用c++库
log4cpp,http://log4cpp.sourceforge.net/,跟log4j一样,不说最重要,绝对是最常用的. zk 客户端,https://blog.csdn.net/yangzhe ...