java的数据类型
java当中的数据类型分为两种:
基本数据类型
引用数据类型
基本数据类型与引用数据类型的区别在于:
我们知道,局部变量是存储在栈当中,基本数据类型在栈当中直接存储值,而引用数据类型在栈当中存储的是值的一个引用地址,引用的具体对象在堆中。
例如这张图:
左边为栈,右边为堆。
引用数据类型一般是类对象,或者类似类对象,我认为是因为引用数据类型无法直接用一个值存储所以才存在引用这种说法的,引用当中存在着一些结构和数据的引用集合。
引用数据类型主要有以下几种:类对象、枚举对象、注解对象、接口对象、数组对象
基本数据类型分为以下8种:
数值类型:
整型:
按范围大小分为以下4种:
字节型 byte(1)、短整型short(2)、整型int(4)、长整型long(8)
整型的默认数据类型是int,long是含有单位的单位为l(或者L)
浮点型:
按照范围分为以下2种:
单精度浮点型float(4)、双精度浮点型double(8)
浮点型的默认数据类型是double,float的单位是f(或者F),double的单位是d(或者为D)
字符型:
char,java中字符采用Unicode编码,一个字符占2个字节.
char类型数据用单引号括起,表示1个字符。char可以与int进行互转,char对应的int值为在ascii码表的该字符的坐标
布尔型:
boolean, boolean类型的值只有2中选择:true和false。
boolean数据类型占4个字节或者是1个字节。根据java虚拟机规范,boolean数据类型在正常声明定义的时候以int存储,占4个字节;boolean数组中的每一个boolean元素以byte存储,占1个字节
数值类型的存储方式以及最值:
java当中的数值是采用补码进行存储和运算的。
有关补码的概念以及求法看我的另外两篇博文:
于是存储方式与如何求补码就有关了。
整数求补码的例子:
如:15 首先确定数据类型,决定了它的字节长度 我们假设它为8位 接下来求15的补码 1、转2进制 0b1111 2、转原码 正数,符号位为0,1111前面补0补齐8-1位,与符号位连接 00001111 3、转反码 00001111 正数的反码与其原码相等 4、转补码 00001111 正数的补码与其原码相等 所以byte类型15的存储是用00001111存储的
求最值:
最大值除去符号位,所以值为2^(位数-1) - 1
最小值,-2^(位数-1),原因参见 补码的来源以及为什么byte的最小值是-128
整数类型的最值如下:
浮点数据的存储与最值求法又不同了
浮点数根据IEEE_754-1985标准进行存储, 浮点数在计算机内的存储方式
因为存储方式不一样,所以最值并不是很好推论得到。
注意点:
因为小数转二进制可能无法精确转换,所以浮点数是不一定能完全精确存储的
float单精度浮点数的数据范围比long长整型表示的要大,这个根据最值比较推论得到
10^38 > 8^38 > 2^114 > 263
类型转换:
类型转换分为2中:
自动类型转换
只需要简单的赋值给其他数据类型,虚拟机就可以完成类型转换了
强制类型转换
类型转换的时候指定要转换成为的数据类型,相当于更新操作的再确定操作
public class TypeConvert { public static void main(String[] args) { //自动类型转换例子 int i = 0; double d = i; //强制类型转换例子 int j = (int)d; //小范围转大范围默认可以自动类型转化 byte b = 0; short s = 0; s = b; j = b; j = s; long l = s; //char类型进行转换 char数值对应字符在ascii表的位置, char类型转换相当于int char c = 'a'; i = c; l = c; d = c; s = (short)c; //boolean在计算机中存储使用是int格式或者是byte存储, 布尔数据不能和数值类型进行互转 boolean flag = true; //i = flag; //b = (byte)flag; //String str = "nihao"; //s = str; //System.out.println("i=" + i); //System.out.println("d=" + d); //System.out.println("d=" + ); //System.out.println("d=" + ); // } }
什么数据类型之间可以进行自动类型转换?什么类型之间必须进行强制类型转换呢?
byte、short、int、long、float、double
小范围转大范围都可以进行自动类型转换,大范围转小范围必须进行强制类型转换
char类型也可以和数值类型进行类型转换,它>short 并且<int
boolean类型无法和其他类型进行类型转换
数据运算后的数据类型与自动类型提升
一般地,大范围数据与小范围数据进行运算,结果的数据类型是大范围数据的数据类型
byte、short、char进行运算首先都会将byte、short、char进行类型提升成为int数据类型再进行运算
public class TypeTransfer { public static void main(String[] args) { /* 类型转换 */ //自动类型转换 int a = 10; double b = a; //强制类型转换 相当于确认一遍 double a1 = 0; int a2 = (int)a1; double a3 = 0; float a4 = (float)a3; //char 类型转换 char b1 = 'a'; int b2 = b1; long b3 = b1; short b4 = (short)b1; //boolean 类型转换 不能转换成为其他类型 //boolean c1 = false; //byte c2 = c1; //整数类型默认是int类型,浮点类型默认是double类型 //自动类型提升 //大类型和小类型进行运算,得到的结果是大类型 //byte、short、char short s1 = 10; short s2 = 11; s2 = s2 + s1; char s3 = 'a'; short s4 = s3 + s2; int x = 10; int d1 = (int)(x + 0.1); long d2 = 10l; x = (int)(10l +2); } }
这里需要注意,如果是多个常量进行运算,java虚拟机可能会将运算优化,变成类似赋值语句。
public class TestQuestion2 { public static void main(String[] args) { byte b1=3,b2=4,b; b= (byte) (b1+b2); //常量相加JVM可能会做自动优化 b=3+4; byte c1 = (byte)130;//-126 /* 00000000 000000000 00000000 10000010 10000010 10000001 11111110 */ System.out.println(c1); } }
反编译后:
import java.io.PrintStream; public class TestQuestion2 { public static void main(String[] paramArrayOfString) { int i = 3;int j = 4; int k = (byte)(i + j); k = 7; int m = -126; System.out.println(m); } }
运算当中的类型变化与数据类型提升
一般地,小范围的数据类型数据和大范围的数据类型数据进行运算得到的都会是大范围的数据类型的数据结果。
public class Temp { public static void main(String[] args) { int intNumber = 17 + 17l; } }
byte、short、char类型数据在运算的时候,会自动进行类型提升成为int数据类型进行运算。
也就是说,这3种数据类型进行运算的时候,也遵照大小范围运算的规律,不过,要先提升为int再遵守
public class Temp { public static void main(String[] args) { int intNumber = (int)(17 + 17l); byte b = 10,b1 =10, b2; b2 = (byte)(b1 + b2);//byte数据类型进行运算会提升成为int先,所以得到的结果类型为int,赋值必须强制类型转换 } }
注意:
char值运算的时候转换为int是相当于int该字符在ascii表下标的值