Notes 20180509 : Java基本数据类型

  计算机就是个机器,这个机器由CPU、内存、硬盘和输入输出设备组成。计算机上运行着操做系统,操做系统提供对外的接口供各厂商和开发语言,开发运行在其上的驱动和应用程序。html

  操做系统将时间分红细小的时间碎片,每一个时间碎片都单独分配给一个应用程序(进程),而且频繁的切换。只是由于时间碎片很细小,而且切换速度很快,因此看起来就好像虽有的应用程序都在同时执行同样。java

  对于程序员而言,咱们写程序基本不用考虑其余应用程序,只用想好怎么作本身的事情就OK了。不一样的应用程序可以实现不一样的功能。可是本质上计算机只会执行预先写好的指令而已,这些指令也只是操做数据或者设备。所谓程序基本上就是告诉计算机要操做的数据和执行的指令序列(因此我在一篇文章中写过程序=数据结构+算法),即对什么数据作什么操做。如读文档,就是将数据从磁盘加载到内存,而后CPU处理再将数据返回到内存,内存中的数据输入到输出设备。程序员

  基本上,全部的数据都须要先存放在内存中进行处理,程序的很大一部分工做就是操做在内存中的数据。数据在计算机内部都是以二进制存储的,并无数据类型的概念。这对于程序员而言是很不方便处理的,为了方便操做数据,高级程序语言引入了数据类型和变量的概念。数据类型对数据归类、方便理解和操做,对于Java语言而言数据类型分为基本数据类型和引用数据类型两种,如图4.1所示。在本章节中咱们就来认识一下Java中的数据类型;算法

 

图4.1   Java数据类型安全

1.1 基本数据类型

  在Java中有8种基本数据类型来存储数值、字符和布尔值。这些数据在计算机中或占据不一样的存储空间或者是存储不一样类型的数据,下面咱们来了解一下;数据结构

1.1.1 整数类型

  整数类型用来存储整数数值,即没有小数部分的数值,也叫定点类型。能够是正数、负数,也能够是0(须要注意的是数学上的0.0和计算机中的0.0不一样,数学中的0.0和0是相等的,可是在计算机中0.0和0属于不一样的数据类型,前者是浮点类型,然后者是int类型或者其它整数类型)。根据所占内存的大小不一样,能够分为byte、short、int和long 4种类型。他们所占的内存和取值范围如表4.2所示。整数默认的类型为int型。整数类型是带符号的数值类型。编码

 

图4.2   整数类型(1个字节是8位)spa

1.1.1.1.byte型

  byte类型是有符号数值,使用byte关键字来定义byte型变量,能够一次定义多个变量并对其进行赋值,也能够不进行赋值。byte型是整型中分配内存空间最少的,只分配1个字节,取值范围也是最小的,只在-128~127之间,在使用时必定要注意,以避免数据溢出产生错误。操作系统

【例4.1】定义byte型变量,并对其进行简单赋值操做,验证其几点要素;设计

package cn.basic.datatype.bytes; public class BytePractice{ public static void main(String[] args){ byte a = 45 , b = 127 , c ; System.out.println(a+b);//整数类型的默认类型为int,因此再给byte类型进行运算时会先将其转换为int类型,而后进行运算 //System.out.println(c); 咱们声明了变量却未给其赋值,这里会报未初始化变量,局部变量必须赋值
        /* b = 128 ; byte类型的内存空间为1字节,取值范围为-128-127,因此这里会报损失精度的问题,可是仍然能够经过强制转型来解决,结果就是输出与实际数值不符,这是精度损失形成的 System.out.println(b);*/ } }

注意:成员字段若是没有初始化,那么编译时会自动初始化为默认值。但局部变量若是没有初始化则会在编译时报错“变量未经初始化”;这和类的加载是有关系的,关于类的加载,咱们在之后的JVM中再作叙述。

1.1.1.2.Short型

  Short型是短整型,使用short关键字来定义short型变量,能够一次定义多个变量并对其赋值,也能够不进行赋值。系统给short型在内存中分配2个字节,取值范围也比byte大得多,在-32768~32767之间,虽然取值范围变大,但仍要注意溢出。

【例4.2】定义short型变量

short a = 23 ;   //定义short型变量a、b、c,并赋值给a、b

1.1.1.3.int型

  int型即整型,使用int关键字来定义int型变量,能够一次定义多个变量并对其赋值,也能够不进行赋值。int型变量取值范围很大(4个字节),在-2147483648~2147483647之间,足够在通常状况下使用,因此是整数变量中应用最普遍的。int类型也是整数类型的默认类型。这意味着整数类型若是不作说明,那么会自动转换为int类型。

【例4.3】定义int型变量

int a = 23 , b = 78 ;   ////定义int型变量a、b、c,并赋值给a、b

1.1.1.4.long型

  long型即为长整形,使用long关键字来定义long型变量,能够一次定义多个变量并对其进行赋值,也能够不进行赋值。而在对long型变量进行赋值时结尾必须加上“L”或“l”(由于I和i的大写类似,因此咱们通常使用L,便于阅读。),不然将不被认为是long型,而会被默认做为int型处理,这时可能会出现溢出内存的错误,以下图就是一个溢出的错误。因此当数值过大超过int型范围时就用long型,系统分给long型8个字节,取值范围更大,在-9223372036854775808~9223372036854775807之间。

【例4.4】定义long型变量,并对其进行一些分析;

package cn.basic.datatype.longs; public class LongPractice{ public static void main(String[] args){ long a = 3890 , b;     //当咱们定义一个变量时若是他的数值超过int的范围,却又不对其进行末尾强制, //b = 922337203685477 ; 那么程序会将其当作int处理,则会发生错误,提示超出范围 //System.out.println(b); 提示咱们数值过大
 System.out.println(a); b = 922337203685477L; System.out.println(b); b = 922337203685477l; System.out.println(b); //b = 922337203685477 L; 咱们在定义long型变量时要注意,初始化的后面紧跟"L"或"l",不能有空格的存在,不然会提示错误
 System.out.println(b); } }

咱们在定义long型数据时末尾最好加L,由于l和1是很差区分的;

上面的四种整数类型在Java程序中有3种表示形式,分别为十进制、八进制、和十六进制。

【例4.5】整数的各型运算

package cn.basic.datatype.integer; public class IntegerPractice{ public static void main(String[] args){ byte a = 127 ; short b = 3276 ; int c = 214748364 ; long d = 21474836423444L ; long resultL = a + b + c + d ; //int resultD = a + b + c + d ;当一个高精度的数据类型向低精度转换时,会报可能损失精度的错误 //int dd = (int)d;
        int dd = new Long(d).intValue(); int resultD = a + b + c + dd ; System.out.println("结果为"+resultL); System.out.println("结果为"+resultD); } }

 

1.1.2 浮点类型

  在计算机系统的发展过程当中,曾经提出过多种方法表示实数,可是到目前为止使用最普遍的是浮点表示法。相对于定点数而言,浮点数利用指数使小数点的位置能够根据须要而上下浮动,从而能够灵活地表达更大范围的实数。如上面的4中整数类型都是属于定点类型。浮点类型表示有小数部分的数字。Java语言中浮点类型分为单精度浮点类型(float)和双精度浮点类型(double),它们具备不一样的取值范围,如图所示。浮点型默认的类型为double。

1.1.2.1 float型

  float型即为单精度浮点型,使用float关键字来定义float型变量,能够一次定义一个或多个变量并对其进行赋值,也能够不进行赋值。在对float型进行赋值时末尾必须加上“f”或“F”,若是不加,系统会将其默认做为double型来处理,float型的取值范围在1.4E-45~3.4028235E38之间。

【例4.6】对float型进行定义;

package cn.basic.datatype.floats; public class FloatPractice{ public static void main(String[] args){ Float a = 1.4E-45F ; System.out.print(a); } }

1.1.2.2 double型

  double型即双精度浮点型,使用double关键字来定义double型变量,能够一次定义多个变量并对其进行赋值,也能够不进行赋值。在给double型赋值时,可使用后缀“D”或“d”明确代表这是一个double类型数据,但加不加并无硬性要求,能够加也能够不加,double型变量的取值范围在4.9E-324和1.2976931348623157E-308之间。

  单精度和双精度的区别咱们会专门在一篇涉及精度的文章中讲解。

【例4.6】定义一个double型变量和float型变量,并对它们进行赋值、运算和输出;

package cn.basic.datatype.doubles; class DoublePractice{ public static void main(String[] args){ double a = 987.987123456789012D , b = 789.789879887918799d ; double c = 68.8978978977 ; float aa = 987.987123F ;        //当咱们定义一个float型变量却又不对其进行末尾"F"或"f",那么会提示错误可能损失精度
        float d = 987.987123456789012F ; float e = 987.987153456789012F , f = 987.987144456789012f ; System.out.println(a+"和"+b) ; System.out.println(c) ; System.out.println(aa+"和"+d+"和"+e+"和"+f) ; } }

 

1.1.3 字符类型

  在Java的基本数据类型中,咱们最难以说清楚的只怕就是char类型了,固然不少开发人员可能不引觉得然,认为char不就是单引号括起来的一个字符吗?其实否则,char表明一个字符,但是这个字符倒是要存储到计算机中的,这就牵涉到了编码的问题(计算机只能表示数值类型的数据)。Java是使用Unicode做为默认编码的,要想真正弄清楚char,那么咱们须要先从Unicode编码讲起。

  了解了Unicode,咱们就明白了在Java中为何使用Unicode做为默认的编码集,Char型即字符类型。使用char关键字进行声明,用于存储单个字符,在定义字符型变量时,要用单引号‘’括起来。如‘s’表示一个字符,且单引号中只能有一个字符,多了就不是字符类型,而是字符串类型,须要用双引号进行声明。char类型描述的是UTF-16编码中的一个代码单元(这也就是为何char须要两个字节的存储空间了)。

  与C、C++语言同样,Java语言也能够把字符做为整数对待,因为Unicode编码采用无符号编码,能够存储65536个字符(0x0000~0xffff),因此Java中的字符几乎能够处理全部国家的语言文字。若想获得一个0~65536之间的数所表明的Unicode表中相应位置上的字符,也必须使用char型显式转换。

  注意:Java使用Unicode编码,可是要注意这里面的区别,Unicode是一个很大的字符编码集,分为多层,而char使用的是UTF-16编码,因此才有65536这一说。

  在字符类型中有一种特殊的字符,以反斜线“\”开头,后跟一个或多个字符,具备特定的含义,不一样于字符原有的意义,叫作转义字符,Java中的转义字符以下所示。

 

注意:转义字符也是字符,因此在使用时一样要加‘’单引号。

【例4.7】建立一个类CharPractice,实现将Unicode表中某些位置上的一些字符以及一些字符在Unicode表中的位置在控制台上面输出。

package cn.basic.datatype.ch; class CharPractice{ public static void main(String[] args){ int a = 'd' , aa = 97 ; char b = 97 , c = 'a' ; char d = '\\' , e = '\b' , f = '\n' , g = '\u2605' , h = '\u0052' ; //转义字符
        char i = '\u4e08'; System.out.println(a+"和"+aa+"和"+b+"和"+c) ; System.out.println(d+"和"+e+"和"+"和"+g+"和"+h) ; System.out.println(f) ; System.out.println(i); } }

注意:char描述的只是UTF-16的一个代码单元,不能彻底表示Unicode中的全部字符.因此咱们在程序中建议使用String.

1.1.4 布尔类型

布尔类型又称逻辑类型,只有“true”和“false”两个值,分别表明布尔逻辑中的“真”和“假”,使用boolean关键字来声明布尔类型变量,一般被用在流程控制中做为判断条件。

【例4.8】声明一个布尔变量,并对其进行输出;

     boolean abc = true , cba = false ; System.out.println(abc+"仍是"+cba) ; if(abc)System.out.println("真就是真!"); else{ System.out.println("假就是假!"); } if(cba)System.out.println("真就是真!"); else{ System.out.println("假就是假!"); }

 

1.2 引用数据类型

  Java中除了提供基本数据类型外,还提供了引用数据类型,讲起引用数据类型就不得不说面向对象了;

  Java是一种面向对象的设计语言,它将具备相同属性和行为的一类事物封装进类中,咱们研究的时候只有研究该类的一个抽象个体,这个个体就是对象。对象也是一种数据类型,在内存中分配内存空间,经过引用来访问,这就是引用数据类型,关于引用详见揭秘对象。

  Java中引用数据类型和基本数据类型的不一样就在于存储的位置和所能实现的功能。基本数据类型根据做用域分为运行时常量池和局部变量表中,而引用类型倒是都存放在堆中,基本数据类型只是用来做为运算的数据,而对象则是类的一个实例,其中包含了类中数据的一份copy和功能的实现。所能实现的功能也截然不同。关于引用类型咱们认识到这里也就能够了。

1.3 数据类型转换

  类型转换是将一个值从一种类型更改成另外一种类型的一个过程。例如,能够将String类型数据“457”转换为一个数值型,并且能够将任意类型的数据转换为String类型。数据类型转换有不少种,这里咱们只讲解基本数据类型的转换,至于基本数据类型和引用数据类型的转变(自动拆装箱),后边咱们会在其它文章中叙述。

  基本数据类型的转换若是从低精度数据类型向高精度数据类型转换,则永远不会溢出,而且老是成功的;而把高精度数据类型向低精度数据类型转换时则必然会提示有精度损失,有可能失败(取决于高精度数据精度是否超过了低精度的最高精度位)。

  数据类型转换有两种方式,即隐式转换和显示转换。

1.3.1 隐式数据类型转换

  从低精度类型向高精度类型的转换,系统将会自动执行,程序员无需进行任何操做。这种类型的转换称为隐式转换,也叫自动类型转换。下列基本数据类型会涉及数据转换,不包括逻辑类型和字符类型。这些类型按精度从低到高排列顺序为byte < short < int< long < float < double。

注意:byte,short,char之间不会互相转换,他们三者在计算时首先会转换为int类型,有多种类型的数据混合运算时,系统首先自动的将全部数据转换成容量最大的那一种数据类型,而后再进行计算。

【例4.9】将下面int型数据转换为float型数据;

int x = 50 ; float y = x ; System.out.println(y) ; //输出的结果为50.0

隐式数据类型转换也须要遵照必定的规则,那么在运算时各个类型之间要怎么转换呢?各类状况下数据类型之间转换通常遵照以下规则。

 

【例4.10】建立一个类ImplicitConvertPractice,在这个类中声明各类基本数据类型变量,而后进行一系列操做,查看结果。

复制代码
package cn.basic.datatype.change; class ImplicitConvertPractice{ public static void main(String[] args){ byte a = 127 ; short b = 37 ; char ch = 'a' ; System.out.println(ch) ; int xy = a + b + ch ; System.out.println("当byte short和char一块儿运算时,他们会先转换为int型在进行计算,由于整数类型默认为int型: " + xy) ; int x = 50 ; long c = 922068547 ; float y = x ; double d = 92233747.9798698 ; System.out.println("当byte型和short型在一块儿运算时其运算结果为:" + (a+b) ) ; System.out.println("当byte、short型和int型在一块儿运算时其运算结果为:" + (a+b+x)) ; System.out.println("当byte、short、int型和long型在一块儿运算时其运算结果为:" + (a+b+c+x)) ; System.out.println("当byte、short、int、long型和float型在一块儿运算时其运算结果为:" + (a+b+x+c+y)) ; System.out.println("当byte、short、int、long、float型和double型在一块儿运算时其运算结果为:" + (a+b+c+x+y+d)) ; } }
复制代码

  并非全部的隐式转换都是安全的,隐式转换也要注意精度的问题,若是咱们在运算过程当中低精度向高精度转换时超出了高精度的取值范围,那么也会形成精度损失的问题,以下代码演示

    /**
     * 隐式转换也不近是安全的
     */
    @org.junit.Test
    public void test1(){
        int i = Integer.MAX_VALUE - 3;
        byte b = 4;
        int a = i + b;
        System.out.println("i="+i+"  b="+b+"  a="+a);
    }

咱们看到最后的结果和预想的不一致,这就是运算过程当中超出最高精度,形成损失的结果。

1.3.2 显式数据类型转换

  当把高精度的变量赋值给低精度的变量时,必须使用显式类型转换(又叫强制类型转换)。语法以下:

  (低精度类型名)要转换的值

  当咱们把一个高精度想一个低精度转换时,不可超出这些变量取值范围,不然会发生数据溢出的现象,此时会形成数据丢失,因此在使用强制类型转换时,必定要加倍当心,不要超出变量的取值范围,不然就得不到的想要结果。好比咱们进行一次byte和short之间的显示转换

byte a = 127 ; short b = 516 ; byte ab = (byte)b ; //因为short的范围超出了byte的127因此发生溢出,数据损失 System.out.println(ab) ; //结果为4

原理以下:

 

boolean类型不能被转换为其余类型,反之亦然;

【例4.11】咱们建立一个类ExplicitConvertPractice,声明各类数据类型,并对其进行转换操做;

复制代码
package cn.basic.datatype.change; class ExplicitConvertPractice{ public static void main(String[] args){ byte a = 127 ; short b = 516 ; byte ab = (byte)b ; byte abc = (byte)(b - a - a - a - a) ; char ch = 'a' ; System.out.println(ch) ; int xy = a + abc + ch ; System.out.println("当byte short和char一块儿运算时,他们会先转换为int型在进行计算,由于整数类型默认为int型: " + xy) ; System.out.println("当数据范围过大时会发生数据损失: "+ ab ) ; //显示转换数据丢失 System.out.println("当数据范围合适时显示转换: "+ abc ) ; int x = 50 ; double d = 92247.8698 ; int bx = (int)(d - x) ; System.out.println("当double型和int型在一块儿强制转换时结果为为:" + bx ) ; boolean boo = false; //System.out.println((int)boo);  } }
复制代码

【例4.12】:分析System.out.println(‘a’)与System.out.println(’a’+1) 的区别;byte b1=3,b2=4,b;    b=b1+b2;      b=3+4;  哪句是编译失败的呢?为何呢?

复制代码
class QuestionPractice{ public static void main(String[] args){ char a = 'a' ; System.out.println('a') ;//由于字符类型没有参与运算,因此仍以字符类型输出  System.out.println(a); System.out.println('a'+1) ;//字符类型和一个常量进行运算,字符类型和常量会都先转换为int类型,而后运算 byte b1 = 3 , b2 = 4 , b3 , b4 ; // b3 = b1 + b2 ; b1和b2是变量,由于变量的值会变化,不肯定具体的值,因此默认使用int类型进行存储,他会先自动转换为int型,计算结果为int型,而b3是byte型,是强制转换, b3 = (byte)(b1 + b2) ; b4 = 3 + 4 ; //3和4都是常量,因此java在编译时期会检查该常量的和是否超出byte类型的范围。若是没有能够赋值。  System.out.println(b3); System.out.println(b4); } }
复制代码

分析:当咱们声明一个字符变量,并对它进行输出时,那么咱们这是输出的就只是一个字符,当咱们对着个字符比变量实现运算输出时,那么这时字符会先转换成int型而后计算,结果以int型输出;

1.4 计算机中的默认值

  咱们知道成员变量是能够只声明不赋值的,可是局部变量却必须声明并赋值才能使用,那么这是为何呢?这其实和类的加载有关系。关于类的加载,我放在后面JVM中讲解;这里咱们只看一下各类数据类型在类加载后的默认值。

复制代码
package basic.value; public class Test { public int i;//全部数值类型默认初始化为0 public static byte bb; public final byte bbb = 45;//成员若是被final修饰,那么意味着是常量,此时必须赋值 char ch; short s; long l; float f; double d;//浮点类型默认是0.0 boolean b;//布尔默认false public static void main(String[] args) { Test test = new Test(); System.out.println(bb);//静态方法中能够直接调用静态,非静态只能初始化后才能加载  System.out.println(test.s); System.out.println(test.i); System.out.println(test.l); System.out.println(test.ch); System.out.println(test.f); System.out.println(test.d); System.out.println(test.b); } }
复制代码

  这里没有列出引用类型,可是引用类型若是没有赋值也是有默认值的,引用类型是null;

多学一点:精度问题

  在上文咱们几回说到了精度的损失问题,这里我特意总结了一篇精度损失的问题来探讨这个问题,能够做为一家之言帮助理解;

相关文章
相关标签/搜索