一、Java数据类型基本概念:
数据类型在计算机语言里面,是对内存位置的一个抽象表达方式,可以理解为针对内存的一种抽象的表达方式。接触每种语言的时候,都会存在数据类型的认识,有复杂的、简单的,各种数据类型都需要在学习初期去了解,Java是强类型语言,所以Java对于数据类型的规范会相对严格。数据类型是语言的抽象原子概念,可以说是语言中最基本的单元定义,在Java里面,本质上讲将数据类型分为两种:基本类型和引用数据类型。
基本类型:简单数据类型是不能简化的、内置的数据类型、由编程语言本身定义,它表示了真实的数字、字符和整数。
引用数据类型:Java语言本身不支持C++中的结构(struct)或联合(union)数据类型,它的复合数据类型一般都是通过类或接口进行构造,类提供了捆绑数据和方法的方式,同时可以针对程序外部进行信息隐藏。
二、Java中的数据类型与内存的关系
在Java中,每个存放数据的变量都是有类型的,如:
char ch; float x; int a,b,c;
ch是字符型的,就会分配到2个字节内存。不同类型的变量在内存中分配的字节数不同,同时存储方式也是不同的。
所以给变量赋值前需要先确定变量的类型,确定了变量的类型,即确定了数据需分配内存空间的大小,数据在内存的存储方式。
三、Java数据类型在内存中的存储:
1)基本数据类型的存储原理:所有的简单数据类型不存在“引用”的概念,基本数据类型都是直接存储在内存中的内存栈上的,数据本身的值就是存储在栈空间里面,而Java语言里面八种数据类型是这种存储模型;
2)引用类型的存储原理:引用类型继承于Object类(也是引用类型)都是按照Java里面存储对象的内存模型来进行数据存储的,使用Java内存堆和内存栈来进行这种类型的数据存储,简单地讲,“引用”是存储在有序的内存栈上的,而对象本身的值存储在内存堆上的;
区别:基本数据类型和引用类型的区别主要在于基本数据类型是分配在栈上的,而引用类型是分配在堆上的(需要java中的栈、堆概念),
基本类型和引用类型的内存模型本质上是不一样的。
例1:我们分析一下”==“和equals()的区别。
首先,我定义两个String对象
Stringa="abc";
Stringb="abc";
然后
if(a==b){
System.out.println("a==b");
}else{
System.out.println("a!=b");}
程序输出a!=b
原因:a和b的地址是不相同的,a==b比较的是两个变量的地址
例2:定义两个基本类型
int a=4;
int b=4;
if(a==b){System.out.println("a==b");}
else
{System.out.println("a!=b");}
输出:a==b
原因:==比较的是两个变量的内容
猜想:不论是基本数据类型还是引用类型,他们都会先在栈中分配一块内存,对于基本类型来说,这块区域包含的是基本类型的内容;而对于对象类型来说,这块区域包含的是指向真正内容的指针,真正的内容被手动的分配在堆上。
四、基本数据类型:
byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0
short:短整型,在内存中占16位,即2个字节,取值范围-32768~32717,默认值0
int:整型,用于存储整数,在内在中占32位,即4个字节,取值范围-2147483648~2147483647(-2^31 到(2^31 - 1)),默认值0
long:长整型,在内存中占64位,即8个字节,取值范围-2^63~2^63-1,默认值0L
float:浮点型,在内存中占32位,即4个字节,用于存储带小数点的数字(与double的区别在于float类型有效小数点只有6~7位),默认值0.0
double:双精度浮点型,用于存储带有小数点的数字,在内存中占64位,即8个字节,默认值0.0
char:字符型,用于存储单个字符,占16位,即2个字节,取值范围0~65535,默认值为空
boolean:布尔类型,占1个字节,用于判断真或假(仅有两个值,即true、false),默认值false
五、java类型介绍
1、概述:
Java中的数据类型分为引用数据类型和基本数据类型。
引用数据类型分5种:类,接口,数组、枚举 、标注;
基本数据类型又分布尔类型和数值类型;
布尔类型:boolean(逻辑型) trure or false默认是false;
数值类型分定点类型和浮点类型;
定点类型分整数类型和字符型;
2、JAVA变量的默认初始化
类型 | 默认初始化值 |
boolean | false |
int | 0 |
short | 0 |
float | 0.0 |
double | 0.0 |
char | \ |
long | 0 |
byte | 0 |
object | null |
3、类型详细讲解:
1)整数类型:byte、short、int、long都是表示整数的,只不过他们的取值范围不一样。
byte(字节类型) 一个byte 8位,取值范围为-128~127,占用1个字节(-2的7次方到2的7次方-1)默认是0
short(短整型) 一个short 16位,取值范围为-32768~32767,占用2个字节(-2的15次方到2的15次方-1)默认是0
int(整型) 一个int 32位,取值范围为(-2147483648~2147483647),占用4个字节(-2的31次方到2的31次方-1)默认是0
long(长整型) 一个long 64位,取值范围为(-9223372036854774808~9223372036854774807),占用8个字节(-2的63次方到2的63次方-1)默认是0L或0l推荐用大写;
可以看到byte和short的取值范围比较小,而long的取值范围太大,占用的空间多,基本上int可以满足我们的日常的计算了,而且int也是使用的最多的整型类型了。在通常情况下,如果JAVA中出现了一个整数数字比如35,那么这个数字就是int型的,如果我们希望它是byte型的,可以在数据后加上大写的 B:35B,表示它是byte型的,同样的35S表示short型,35L表示long型的,表示int我们可以什么都不用加,但是如果要表示long型的,就一定要在数据后面加“L”。
1.1)定点常量
定点常量是整型常数,它可用十进制、八进制、十六种进制三种方式来表示。
十进制定点常量:如123、-456、0。
八进制定点常量:以0前导,形式为0dd...d。如0123表示十进制数83,-011表示十进制数-9。
十六进制定点常量:以0x或0X开头,如0x123表示十进制数291,-0X12表示十进制数-18。
1.2)定点变量
定点变量即整型变量,可细分成字节型变量、整型变量、短整型变量和长整型变量四种。
对各种定点变量的开销内存字节数和数值范围作简要说明。
需要注意的是,如果要将一定点常量赋值给一个定点变量,需要查验常量是否在该变量的表达范围内,如超出范围程序会编译出错。
2)char型(字符型)
Java中一个字符(char)表示Unicode字符集中的一个元素。
Unicode字符由16位组成,因此,有(65535)个不同的字符可用,
Unicode字符集包含所有不同语言的字符,以及数学、科学、文字中的常用符号,所以给了我们很大的灵活性。
字符由单引号括起来的单个字符表达,通常用16进制表示,
范围从’’到’?’(u告诉编译器你在用两个字节[16位]字符信息表示一个Unicode字符)。
用于存放字符的数据类型,占用2个字节,采用unicode编码,它的前128字节编码与ASCII兼容,
字符的存储范围在\~\?,在定义字符型的数据时候要注意加' ',比如 '1'表示字符'1'而不是数值1。
2.1)字符常量
字符常量指用单引号括起来的单个字符,如‘a’,‘A’,请特别注意,字符的定界符是单引号,而非双引号。
除了以上所述形式的字符常量值之外,Java还允许使用一种特殊形式的字符常量值,
这通常用于表示难以用一般字符来表示的字符,这种特殊形式的字符是以一个“\”开头的字符序列,称为转义字符。
Java中的常用转义字符见表
符号 | 字符含义 |
---|---|
\n | 换行 (0x0a) |
\r | 回车 (0x0d) |
\f | 换页符(0x0c) |
\b | 退格 (0x08) |
\0 | 空字符 (0x20) |
\s | 字符串 |
\t | 制表符 |
\" | 双引号 |
\' | 单引号 |
\\ | 反斜杠 |
\ddd | 八进制字符 (ddd) |
\uxxxx | 16进制Unicode字符 (xxxx) |
2.2)字符变量
以char定义的变量,如char c='a';
要特别加以说明的是,Java的文本编码采用Unicode集,Java字符16位无符号型数据,一个字符变量在内存中占2个字节。
注:char c = ' 1 ',我们试着输出c看看,System.out.println(c);结果就是1,而如果我们这样输出呢System.out.println(c+0);结果却变成了49,这是因为0是int型,进行了向上类型转换,结果是个int型。
如果我们这样定义c看看,char c = ' \1 ';输出的结果仍然是1,这是因为字符'1'对应着unicode编码就是\1。
3)浮点类型:分float和double是表示浮点型的数据类型,他们之间的区别在于他们的精确度不同。
3.1)浮点常量
即带小数点的实型数值,可以由直接带小数点的数值和科学计数法两种形式来表示:
带小数点的数值形式:由数字和小数点组成,如0.123、.123、123.、123.0。
科学计数法表示形式:由一般实数和e±n(E±n)组成,如12.3e3、5E-3,它们分别表示12.3乘以10的3次方,5乘以10的-3次方。需要注意的是,e或E之前必须有数字,且e或E后面的指数必须为整数。
3.2)浮点变量
浮点变量有单精度变量和双精度变量之分,不同的精度开销的内存字节数和表达的数值范围均有区别。两种浮点变量占内存字节数和数值范围
浮点常量也有单精度和双精度之分,前面列出的常量均是双精度常量,如果要特别说明为单精度常量,可以数据末尾加上f或F作为后缀,如12.34f。如果要特别指明一个浮点常量是双精度常量,数据末尾不需要添加后缀,或者在数据末尾加上d或D作为后缀,如12.34d。
float (单精度浮点型)一个float 32位,占用4个字节,例3.2F,默认是0.0f, 3.402823e+38 ~1.401298e-45(e+38表示是乘以10的38次方,同样,e-45表示乘以10的负45次方)。
double (双精度浮点型)一个dobule 64位 占用8个字节,例3.2,默认是0.0, 1.797693e+308~4.9000000e-324 占用8个字节
注:double型比float型存储范围更大,精度更高,所以通常的浮点型的数据在不声明的情况下都是double型的。
如果要表示一个数据是float型的,可以在数据后面加上“F”。 浮点型的数据是不能完全精确的,所以有的时候在计算的时候可能会在小数点最后几位出现浮动,这是正常的。
相关介绍:
在Java基本类型在使用字面量赋值的时候,有几个简单的特性如下:
1】当整数类型的数据使用字面量赋值的时候,默认值为int类型,就是直接使用0或者其他数字的时候,值的类型为int类型,所以当使用 long a = 0这种赋值方式的时候,JVM内部存在数据转换。
2】浮点类型的数据使用字面量赋值的时候,默认值为double类型,就是当字面量出现的时候,JVM会使用double类型的数据类型。
3】从JDK 5.0开始,Java里面出现了自动拆箱解箱的操作,基于这点需要做一定的说明:
简单类型 | boolean | byte | char | short | Int | long | float | double | void |
二进制位数 | 1 | 8 | 16 | 16 | 32 | 64 | 32 | 64 | -- |
封装器类 | Boolean | Byte | Character | Short | Integer | Long | Float | Double | Void |
对应原始的数据类型,每种数据类型都存在一个引用类型的封装类,分别为Boolean、Short、Float、Double、Byte、Int、Long、Character,这些类型都是内置的封装类,这些封装类(Wrapper)提供了很直观的方法,针对封装类需要说明的是,每种封装类都有一个xxxValue()的方法,通过这种方法可以把它引用的对象里面的值转化成为基本变量的值,不仅仅如此,每个封装类都还存在一个valueOf(String)的方法直接把字符串对象转换为相应的简单类型。
在JDK 5.0之前,没有存在自动拆解箱的操作,即Auto Box操作,所以在这之前是不能使用以下方式的赋值代码的:Integer a = 0;//这种赋值方式不能够在JDK 1.4以及以下的JDK编译器中通过,但是JDK 5.0出现了自动拆解箱的操作,所以在JDK 5.0以上的编译器中,以上的代码是可以通过的
六. 数据类型之间的转换
1).简单类型数据间的转换,有两种方式:自动转换和强制转换,通常发生在表达式中或方法的参数传递时。
自动转换
具体地讲,当一个较"小"数据与一个较"大"的数据一起运算时,系统将自动将"小"数据转换成"大"数据,再进行运算。而在方法调用时,实际参数较"小",而被调用的方法的形式参数数据又较"大"时(若有匹配的,当然会直接调用匹配的方法),系统也将自动将"小"数据转换成"大"数据,再进行方法的调用,自然,对于多个同名的重载方法,会转换成最"接近"的"大"数据并进行调用。这些类型由"小"到"大"分别为 (byte,short,char)--int--long--float—double。这里我们所说的"大"与"小",并不是指占用字节的多少,而是指表示值的范围的大小。
①下面的语句可以在Java中直接通过:
byte b;int i=b; long l=b; float f=b; double d=b;
②如果低级类型为char型,向高级类型(整型)转换时,会转换为对应ASCII码值,例如
char c='c'; int i=c;
System.out.println("output:"+i);输出:output:99;
③对于byte,short,char三种类型而言,他们是平级的,因此不能相互自动转换,可以使用下述的强制类型转换。
short i=99 ; char c=(char)i; System.out.println("output:"+c);输出:output:c;
强制转换
将"大"数据转换为"小"数据时,你可以使用强制类型转换。即你必须采用下面这种语句格式: int n=(int)3.14159/2;可以想象,这种转换肯定可能会导致溢出或精度的下降。
2)表达式的数据类型自动提升, 关于类型的自动提升,注意下面的规则。
①所有的byte,short,char型的值将被提升为int型;
②如果有一个操作数是long型,计算结果是long型;
③如果有一个操作数是float型,计算结果是float型;
④如果有一个操作数是double型,计算结果是double型;
例, byte b; b=3; b=(byte)(b*3);//必须声明byte。
3)包装类过渡类型转换
一般情况下,我们首先声明一个变量,然后生成一个对应的包装类,就可以利用包装类的各种方法进行类型转换了。例如:
①当希望把float型转换为double型时:
float f1=100.00f;
Float F1=new Float(f1);
double d1=F1.doubleValue();//F1.doubleValue()为Float类的返回double值型的方法
②当希望把double型转换为int型时:
double d1=100.00;
Double D1=new Double(d1);
int i1=D1.intValue();
简单类型的变量转换为相应的包装类,可以利用包装类的构造函数。即:Boolean(boolean value)、Character(char value)、Integer(int value)、Long(long value)、Float(float value)、Double(double value)
而在各个包装类中,总有形为××Value()的方法,来得到其对应的简单类型数据。利用这种方法,也可以实现不同数值型变量间的转换,例如,对于一个双精度实型类,intValue()可以得到其对应的整型变量,而doubleValue()可以得到其对应的双精度实型变量。
4)字符串与其它类型间的转换
其它类型向字符串的转换
①调用类的串转换方法:X.toString();
②自动转换:X+"";
③使用String的方法:String.volueOf(X);
字符串作为值,向其它类型的转换
①先转换成相应的封装器实例,再调用对应的方法转换成其它类型
例如,字符中"32.1"转换double型的值的格式为:new Float("32.1").doubleValue()。也可以用:Double.valueOf("32.1").doubleValue()
②静态parseXXX方法
String s = "1";
byte b = Byte.parseByte( s );
short t = Short.parseShort( s );
int i = Integer.parseInt( s );
long l = Long.parseLong( s );
Float f = Float.parseFloat( s );
Double d = Double.parseDouble( s );
③Character的getNumericValue(char ch)方法
总结:只有boolean不参与数据类型的转换
(1).自动类型的转换:a.常数在表数范围内是能够自动类型转换的
b.数据范围小的能够自动数据类型大的转换(注意特例)
int到float,long到float,long到double 是不会自动转换的,不然将会丢失精度
c.引用类型能够自动转换为父类的
d.基本类型和它们包装类型是能够互相转换的
(2).强制类型转换:用圆括号括起来目标类型,置于变量前
七.Java引用类型
Java变量命名规则:
1:必须以字母、下划线“_”、或“$”符号开头
2:可以包括数字、区分大小写
3:不能使用Java语言的关键字,例如int、class、public等
Java有 5种引用类型(对象类型):类 接口 数组 枚举 标注
引用类型:底层结构和基本类型差别较大
JVM的内存空间:(1). Heap 堆空间:分配对象 new Student()
(2). Stack 栈空间:临时变量 Student stu
(3).Code 代码区 :类的定义,静态资源 Student.class
eg:Student stu = new Student(); //new 在内存的堆空间创建对象
stu.study(); //把对象的地址赋给stu引用变量
上例实现步骤:a.JVM加载Student.class 到Code区
b.new Student()在堆空间分配空间并创建一个Student实例;
c.将此实例的地址赋值给引用stu, 栈空间;
个人总结
1、如果小数类型,并且小数比较小,比如四位小数,建议使用 BigDecimal 如果 是 double 类型会有失精度,有的时候会用科学记数法表示;
比如 0.0001 会变成 1.0E-4,试问谁能看懂,如果偏要用 double 还要对类型进行转换。
2、int double 都是有包装类型的,建议使用包装类型,包装类型能区分 null 和 0,就像在spring-mvc接收时使用 int 类型接收值,如果这个属性不传值,ajax 请求会报 400 错误,而且不能区分这个值是否是空;
3、for 循环中如果要对字符串进行拼接,建议使用 StringBuffer ,如果没有线程安全问题,直接使用 StringBuilder,原因StringBuffer的所有操作是保证线程安全的,可以理解成使用了 synchronized 关键字,对性能是有影响的。
4、最后对所有包装类型进行操作(比如 toString())要进行空指针判断,我们并不能保证这个值是有的。
5、(1)、ASCII码中bai:一个英文字母(不分大du小写)占一个字节的空间,一个中文汉字占zhi两个字节的空间。
一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制。最小值0,最大值255。
2)、UTF-8编码中:一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。
3)、Unicode编码中:一个英文字符等于两个字节,一个中文(含繁体)等于两个字节。
符号:英文标点占一个字节;中文标点占两个字节。
举例:英文句号“.”占1个字节的大小;中文句号“。”占2个字节的大小。
4)、UTF-16编码中:一个英文字母字符或一个汉字字符存储都需要2个字节(Unicode扩展区的一些汉字存储需要4个字节)。