Java基础知识之数据类型

(一)数据类型

Java中的数据类型主要分为两大类,包括基本数据类型和引用数据类型,其中基本数据类型分为4类8种,如下图1所示。

Java数据类型

图1:Java数据类型

1、数值型

(1)整型:

byte:占用1个字节,8位(bit),数据范围是-128~127。

short:占用2个字节,16位,数据范围-32768~32767。

int:占用4个字节,32位,数据范围是-2^31~2^31-1。

long:占用8个字节,64位,数据范围是-2^63~2^63-1。

(2)浮点型

float:占用4个字节,32位,数据范围是3.4e-45~1.4e38,直接赋值时必须在数字后面加上f或者F。

double:占用8个字节,64位,数据范围是4.9e-324~1.8e308,赋值时可以加d或D,也可以不加。

2、非数值型

(1)char:占用2个字节,16位,Java字符采用unicode编码,它的前128字节编码与ASCII兼容字符的存储范围在\u0000~\uFFFF,在定义字符型的数据时候要注意加' ',比如 '1'表示字符'1'而不是数值1。char是定长编码,所有的char字符都是2个字节,即16位。

(2)boolean:值只能是true或false。

Java中所有的基本数据类型都有固定的存储范围和所占内存空间的大小,而不受具体操作系统的影响,来保证Java的可移植性。整型数据默认为int类型,浮点数默认为double类型,如果要标识long类型或者float类型,要在数值的后面加上l或L、f或F,否则会出现编译问题。对于char型,也可以当作是整型来看待。

(二)基本数据类型的转换

1、boolean类型不能转换成其他数据类型。

2、自动类型转换:容量小的数据类型可以自动转换成容量大的数据类型,如byte -> short -> int -> long -> float -> double。byte、short、int不会互相转换,他们三者在计算时会转换成int类型。

例子:int a=257;byte b=(byte)a;在java中,int类型占4个字节,byte占一个字节,故int类型转化为byte类型会出现位丢失情况,即将int的低4位作为byte类型的值。int型变量的值为257,对应的二进制是100000001,后8位是00000001,第一个0表示符号位,表示正数,所以变量b的值为1。(补充:关于补码及位运算,可以参见《位运算小结(按位与、按位或、按位异或、取反、左移、右移)》)

3、强制类型转换:容量大的数据类型转换成容量小的数据类型时,要加上强制转换符,但这样有可能会造成精度降低或者数据溢出,要小心。

(三)对象包装器

Java为了能将基本类型视为对象来处理,并能连接相关的方法,Java为每个基本类型都提供了相应的包装类,这样便能将基本类型转化为对象来处理。其对应关系表如下所示:

基本数据类型
包装类
byte(字节)
java.lang.Byte
char(字符)
java.lang.Character
short(短整型)java.lang.Short
int(整型)java.lang.Integer
long(长整型)
java.lang.Long
float(单精度浮点型)
java.lang.Float
double(双精度浮点型)
java.lang.Double
boolean(布尔型)
java.lang.Boolean

专门用来包裹(Wrap)基本类型的类叫包装类,也叫包装器,如Long,Integer等,其主要目的就是提供一个对象实例作为壳,将其基本类型包到这个对象之中,然后提供很多操作数据的方法,使面向对象的编程变得更加容易。

(四)装箱和拆箱

在Java SE 5.0之前,要进行操作后才能将int包装为一个Integer类。JDK 5.0为基本数据类型提供了自动装箱(boxing)和拆箱(unboxing)的功能。

装箱(boxing):将基本数据类型包装秤对应的包装类对象。(如:int >> Integer)

拆箱(unboxing):将包装类对象转换成对应的基本数据类型。(如:Integer >> int)

Java编译器在编译时期会根据源代码的语法来决定是否进行装箱和拆箱。在运算时,也可以进行自动装箱和拆箱。

注意,有一个特殊现象如下:

public class TestDemo {
  public static void main(String[] args) {
    // 分别初始化i1、i2的值为127和128,观察打印出的结果
    Integer i1 = 128;
    Integer i2 = 128;
    if (i1 == i2) {
      System.out.println("i1 == i2");
    } else {
      System.out.println("i1 != i2");
    }
  }
}

运行可以发现,当令i1和i2都为127的时候,输出的结果是i1 == i2,但是,当令i1和i2都为128的时候,输出的结果是i1 != i2。这是因为,Integer类有一个缓存,它会缓存-128~127之间的整数,在这个范围内,调用valueOf的时候,不会生成新的对象,而是从缓存中取出对象,以提高性能。而当在这个范围以外,就会使用构造方法生成新的对象。

(五)泛型

泛型只是编译时的概念,是供编译器进行语法检查用的(由于程序员需要一种类型安全的集合,故这种需求产生了泛型)。使用泛型的目的主要有以下两个方面:

1、努力将运行时的异常转换成编译时错误,减少运行时异常数量(提高了编译器的能力)。

2、解决模版编程的问题。

//不用泛型
List list0 = new ArrayList();
list0.add("hello");
String str0 = (String) list0.get(0);
//用泛型,这样在获取对象的时候就不用类型转换
List<String> list = new ArrayList<String>();
list.add("hello");
String str = list.get(0);

注意:泛型是没有数组的。编译器不承认HashMap<K,V>[]这种形式的:Cannot create a generic array of HashMap<k,v> 。原因就是数组必须确定它每一个元素的类型。但是泛型在编译阶段有一个类型擦除的问题,也就是说编译器理解HashMap<Integer,Integer>和HashMap<String,String>都是同一种类型HashMap。如果泛型数组存在,那么HashMap<Integer,Integer>和HashMap<String,String>对象都可以加入到同一个HashMap[]数组中,这会造成灾难性的结果。 

如果一定要定义HashMap数组,可以使用HashMap[] aTweightList = new HashMap[10]; 形式,也就是HashMap常规类型。

参考资料:

本文标题:Java基础知识之数据类型

本文链接:http://yedward.net/?id=210

本文版权归作者所有,欢迎转载,转载请以文字链接的形式注明文章出处。

相关文章