Java基础类型总结

  最近一直在总结反思自己, 趁着现在请假在学校上课的空余时间,从基础开始重新温故学习下Java,充实下自己。

一、数据类型

从下图中,我们可以很清晰的看出Java中的类型,其中红色方框中的是Java的4种基本数据类型:

下面我们来详细讲解上图中的基本类型:

1.整数类型

   1) 在Java中,整数类型共有4种,它们有固定的表述范围和字段长度,且不受具体的操作系统的影响,保证了Java的跨平台性

   2) Java语言中,整数有三种表现形式,分别是:

    a. 十进制整数,如 120, -31, 0

    b. 八进制整数,要求以0开头(注意这是数字0,不是字母o),如:012,

    c. 十六进制整数,要求以0x开头(注意这是数字0,不是字母o),如: 0x12

   3) Java语言中,默认的整数类型是int类型,声明long类型的时候,后面必须要加个l(字母L的小写,不是大写字母I,也不是数字1)或者L,建议使用大写L,防止和数字1,大写字母I混淆,如:30L, 30l

   4) Java中四种整数类型的表述范围:

  

2.浮点类型

   1) 与整数类型一样,同样有固定的表述范围和字段长度,且不受具体的操作系统的影响,保证了Java的跨平台性

   2) Java语言中,浮点类型有两种表现形式,分别是:

    a. 十进制数形式, 如3.14

    b. 科学计数法,如,3.14e2, 3.14e-2, -3.14E2

   3) Java语言中,默认的浮点数类型是double,声明float类型的时候,后面必须添加字母f或者F,如3.14F,3.14f

   4) Java中两种浮点类型的表述范围:

  

3. 字符类型

   1) 字符类型是用''单引号括起来的单个字符,例如char c = 'w'; char a = '中';

   2) Java字符采用Unicode(全球语言统一编码)编码,每个字符占两个字节,因而可用16进制编码形式表示,如:char c = '\u0061'

   3) Java中允许使用转义字符'\'将其后面的字符转换成其他含义, 如: char c = '\n';  //表示换行

 4.布尔类型

   1) boolean类型的值只有两种:true, false

   2) boolean类型不可以转换为其他的数据类型

5.基本数据类型的转换

   1) boolean不可以转换为其他的数据类型

   2) 整数型,浮点类型,字符型是可以相互转换的,转换时遵守下面的原则:

    a. 容量小的类型自动转换为大的类型,数据类型按容量大小排序为:

     byte, short, char < int < long <float < double

    b. byte, short, char 三种类型间不会相互转换,他们三者在计算时,首先会转换为int类型

    c. 容量大的类型在转换为小的类型的时候,必须加上强制转换符,此时可能造成精度降低或者溢出问题

    d. 有多种数据类型混合计算的时候,系统首先自动转换为容量最大的那个类型再来继续计算

    e. 实数类型默认为double类型,如, 1.2; 整数类型默认为int类型,如 1

二、JVM对基本类型的处理

1.常量池技术

   1) java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。

   2) Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池

   下面我们主要使用Long类型来进行讲解吧。

 首先我们先写一个测试类:

 LongTypeTest.java

1 package com.kevin.basetype;
2 
3 public class LongTypeTest {
4     
5     public static void main(String[] args) {
6         long longParam = 30L;
7         Long longParam2 = 30L;
8     }
9 }
View Code

 我们通过javac命令编译后,再通过jad命令生成编译文件来查看编译信息,如下:

 1 // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
 2 // Jad home page: http://www.kpdus.com/jad.html
 3 // Decompiler options: packimports(3) annotate 
 4 // Source File Name:   LongTypeTest.java
 5 
 6 package com.kevin.basetype;
 7 
 8 
 9 public class LongTypeTest
10 {
11 
12     public LongTypeTest()
13     {
14     //    0    0:aload_0         
15     //    1    1:invokespecial   #1   <Method void Object()>
16     //    2    4:return          
17     }
18 
19     public static void main(String args[])
20     {
21         long longParam = 30L;
22     //    0    0:ldc2w           #2   <Long 30L>
23     //    1    3:lstore_1        
24         Long longParam2 = Long.valueOf(30L);
25     //    2    4:ldc2w           #2   <Long 30L>
26     //    3    7:invokestatic    #4   <Method Long Long.valueOf(long)>
27     //    4   10:astore_3        
28     //    5   11:return          
29     }
30 }
View Code

   从第26行,我们可以看到,使用包装类初始化的时候,调用的是Long类中的valueOf方法,下面我们看看,Long类中的该方法是怎样的。

1     public static Long valueOf(long l) {
2         final int offset = 128;
3         //当 l >= -128 && l <= 127 时,返回常量池中缓存的数据
4         if (l >= -128 && l <= 127) { // will cache
5             return LongCache.cache[(int)l + offset];
6         }
7         //否则初始化一个新的Long对象
8         return new Long(l);
9     }

   从代码中看出,当 l 的值小于127的时候,将会调用LongCache.cache()中获取常量池中的数值。其中,LongCache是一个内部类

 1     //Long类中的私有类
 2     private static class LongCache {
 3     //私有的构造方法,不允许初始化
 4         private LongCache(){}
 5     //static final类型,它的值在编译期间将会确定下来并且被存储到常量池中
 6         static final Long cache[] = new Long[-(-128) + 127 + 1];
 7     //静态代码块,为cache数组赋值
 8         static {
 9             for(int i = 0; i < cache.length; i++)
10                 cache[i] = new Long(i - 128);
11         }
12     }

   其他Byte,Short,Integer,Long,Character,Boolean都是差不多的,具体就不在此重复讲了。

   我们在Double中的valueOf中我们可以看到源代码是这样子的:

1 public static Double valueOf(double d) {
2     //直接初始化并返回一个Double对象
3     return new Double(d);
4 }

   Float亦是如此。

2.short, int, char -> byte(char)

 看到这个,估计大家都很奇怪,这个标题究竟是什么意思呢?下面我们就来讲解下:

   1) 当short, int, char 的数值小于127大于-128时,编译器在内存中会使用byte类型来进行记录。

   2) 当short, int, char 的值大于127却小于 215-1时,编译器在内存中会使用char类型来进行记录。

  换句话来说,byte, short, int, char四个基本类型,编译器在内存中将会使用最小的单位去存储他们的值的内容。

接着我们先写个测试类来验证下:

 1 package com.kevin.basetype;
 2 
 3 public class BaseType {
 4     
 5     public static void main(String[] args) {
 6         byte bytePram = 10;
 7         Byte bytePram2 = 10;
 8         
 9         short shortParam = 40;
10         Short shrotParam2 = 40;
11         
12         int intParam = 20;
13         int intParam2 = 20;
14         Integer integerParam = 20;
15 
16         long longParam = 30;
17         Long longParam2 = 30L;
18         
19         double doubleParam = 20.0;
20         double doubleParam4 = 20.0;
21         Double doubleParam2 = 20.0;
22         Double doubleParam3 = 20.0;
23         
24         float floatParam = 20.0f;
25         Float floatParam2 = 20.0f;
26         
27         boolean booleanParam = true;
28         Boolean booleanParam2 = true;
29         
30         char charParam = 'a';
31         char charParam2 = 'a';
32         Character characterParam = 'a';
33     }
34 }
View Code

   2)继续查看编译信息:

 1 // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
 2 // Jad home page: http://www.kpdus.com/jad.html
 3 // Decompiler options: packimports(3) annotate 
 4 // Source File Name:   BaseType.java
 5 
 6 package com.kevin.basetype;
 7 
 8 
 9 public class BaseType
10 {
11 
12     public BaseType()
13     {
14     //    0    0:aload_0         
15     //    1    1:invokespecial   #1   <Method void Object()>
16     //    2    4:return          
17     }
18 
19     public static void main(String args[])
20     {
21         byte byte0 = 10;
22     //    0    0:bipush          10
23     //    1    2:istore_1        
24         Byte byte1 = Byte.valueOf((byte)10);
25     //    2    3:bipush          10
26     //    3    5:invokestatic    #2   <Method Byte Byte.valueOf(byte)>
27     //    4    8:astore_2        
28         byte byte2 = 40;
29     //    5    9:bipush          40
30     //    6   11:istore_3        
31         Short short1 = Short.valueOf((short)40);
32     //    7   12:bipush          40
33     //    8   14:invokestatic    #3   <Method Short Short.valueOf(short)>
34     //    9   17:astore          4
35         byte byte3 = 20;
36     //   10   19:bipush          20
37     //   11   21:istore          5
38         byte byte4 = 20;
39     //   12   23:bipush          20
40     //   13   25:istore          6
41         Integer integer = Integer.valueOf(20);
42     //   14   27:bipush          20
43     //   15   29:invokestatic    #4   <Method Integer Integer.valueOf(int)>
44     //   16   32:astore          7
45         long l = 30L;
46     //   17   34:ldc2w           #5   <Long 30L>
47     //   18   37:lstore          8
48         Long long1 = Long.valueOf(30L);
49     //   19   39:ldc2w           #5   <Long 30L>
50     //   20   42:invokestatic    #7   <Method Long Long.valueOf(long)>
51     //   21   45:astore          10
52         double d = 20D;
53     //   22   47:ldc2w           #8   <Double 20D>
54     //   23   50:dstore          11
55         double d1 = 20D;
56     //   24   52:ldc2w           #8   <Double 20D>
57     //   25   55:dstore          13
58         Double double1 = Double.valueOf(20D);
59     //   26   57:ldc2w           #8   <Double 20D>
60     //   27   60:invokestatic    #10  <Method Double Double.valueOf(double)>
61     //   28   63:astore          15
62         Double double2 = Double.valueOf(20D);
63     //   29   65:ldc2w           #8   <Double 20D>
64     //   30   68:invokestatic    #10  <Method Double Double.valueOf(double)>
65     //   31   71:astore          16
66         float f = 20F;
67     //   32   73:ldc1            #11  <Float 20F>
68     //   33   75:fstore          17
69         Float float1 = Float.valueOf(20F);
70     //   34   77:ldc1            #11  <Float 20F>
71     //   35   79:invokestatic    #12  <Method Float Float.valueOf(float)>
72     //   36   82:astore          18
73         boolean flag = true;
74     //   37   84:iconst_1        
75     //   38   85:istore          19
76         Boolean boolean1 = Boolean.valueOf(true);
77     //   39   87:iconst_1        
78     //   40   88:invokestatic    #13  <Method Boolean Boolean.valueOf(boolean)>
79     //   41   91:astore          20
80         byte byte5 = 97;
81     //   42   93:bipush          97
82     //   43   95:istore          21
83         byte byte6 = 97;
84     //   44   97:bipush          97
85     //   45   99:istore          22
86         Character character = Character.valueOf('a');
87     //   46  101:bipush          97
88     //   47  103:invokestatic    #14  <Method Character Character.valueOf(char)>
89     //   48  106:astore          23
90     //   49  108:return          
91     }
92 }
View Code

看完上面以后,大家可能会有这么一个疑问:short, char都是两个字节,为什么存储的时候,会选择使用char类型来进行存储二不选择short呢?

解答:因为short是有符号的,而char类型是无类型的,可以表示的数值范围比short大,所以虽然同样是两个字节,但是却选择了char类型而不选择short类型进行值存储。

3.final, Number, Comparable与基础类型包装类的关系

    1) 所有的基本类型的包装类都使用了final来进行修饰,保证了系统的安全性,试想一下,假设有人也自定义了这么一个java.lang.Integer同时继承了jdk中的java.lang.Integer,并且在里面实现了一些破坏性的代码,那后果将不堪设想了对吧。

    2) 除了Character,Boolean以外,其他的基本类型包装类都继承了抽象类Number。这个抽象类要求继承类必须实现将当前类型的值转换为其他类型的值方法

    3)所有的基本类型包装类都实现了接口Comparable。这个接口的作用是:

    a. 当List/Array中的对象实现了该接口的话,可以直接用Collections.sort()方法进行自动排序

    b. 当一个普通的Object对象实现了该接口,那么将可以用作具有自动sort作用(例如TreeMap)的Map集合中的排序依据key或者具有自动sort作用的Set集合中的排序根据对象

 

  

 

 

 

posted @ 2013-09-03 09:00  小学徒V  阅读(3707)  评论(6编辑  收藏  举报