Java中的基本数据类型与包装类

这篇来说说基本数据类型与其对应的包装类.

基本数据类型有8种(<Java编程思想>中把void也算作基本数据类型,所以有9种的说法.),4中整数类型,2种浮点类型,1中字符类型,1种布尔类型.每种基本数据类型都有其对应的包装类,下面这个表格列出了基本数据类型,占用多少空间,表示范围与它的包装类类型(这里把void也写进去了.):

基本数据类型占用内存大小最小值最大值默认值包装类类型
boolean???falseBoolean
char16bits065535''(什么都没有)Character
byte8bits-1281270Byte
short16bits-2^152^15+10Short
int32bits-2^312^31-10Integer
long64bits-2^632^63-10Long
float32bits1.4e-453.4028235e+380.0Float
double64bits4.9e-3241.7976931348623157e+3080.0Double
void????Void

Java中数值都有正负号.

最大值最小值我们无须刻意记忆,因为其包装类中分别提供了两个常量:

最大值:类型.MAX_VALUE
最小值:类型.MIN_VALUE

为什么把<Java编程思想>会把void也算进去?下面摘抄了一个可能的原因:

众所周知,Java的类型分成两种,一种是基本类型,一种是引用类型。两种的本质区别就是:基本类型是在堆栈处分配空间存“值”。但是引用类型,是在里面分配空间存“值”。Void是不能new出来,也就是不能在堆里面分配空间存对应的值。那就是一开始在堆栈处分配好空间了。所以,有些人将Void归成基本类型,也有道理

在程序设计中经常用到一系列类型,它们需要特殊对待.可以把它们想象成"基本"类型.之所以特殊对待,是因为new将对象存储在"堆"里,故用new创建一个对象--特别是小的、简单的变量,往往不是很有效.因此,对于这些类型,Java采取与C和C++相同的方法.也就是说,不用new来创建变量,而是创建一个并非是引用的"自动变量".这个变量直接存储"值",并置于堆栈中,因此更加高效.

 

自动装箱与自动拆箱

现在我们对于基本数据类型与包装类的转换可以直接这样:

        Integer integer1 = 19970912;
        int i = integer1;

但是在Java SE5之前,这是不可能的,需要进行以下步骤:

        Integer integer1 = Ingeter.valueOf(19970912);
        Integer integer2 = new Integer(19970912);
        int i = integer1.intValue();  //float就是调用floatValue(),以此类推.

出于种种原因,在Java SE5的时候,加入了自动拆箱与装箱的功能.其实底层还是调用了构造器或者对应的xxxValue(),我们利用JDK自带的反汇编器来看一下,先来看看原文件的代码:

public class Test{
	public static void main(String[] args){
		Integer i = 100;
		int number = i;
		System.out.println(i);
	}
}

首先在命令提示符窗口对源文件执行javac操作,得到class文件后输入javap命令(这里需要加.class),这里用-c参数,可以获得较多的信息:

    javap -c c:\Test.class

之后回车,可以得到如下输出: 

C:\Users\Administrator>javap -c c:\Test.class
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: bipush        100
   →→→ 2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       5: astore_1
       6: aload_1
   →→→ 7: invokevirtual #3                  // Method java/lang/Integer.intValue:()I
      10: istore_2
      11: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
      14: aload_1
      15: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      18: return
}

别的先不看,只看前面标→→→的两行,其中#后面的数字对应了这条指令对应了代码的第几行.

在"Integer i = 100;"中,可以看到虚拟机自动调用了Integer的静态方法valueOf(),而"int number = i;"中,则调用了intValue().这也就是自动拆箱与装箱的底层实现原理.

包装类中的方法

    public static int parseInt(String s, int radix)
                    throws NumberFormatException

那么为什么要出现包装类呢,在实际的代码编写过程中,有时候我们定义了一个基本数据类型变量,突然想要对其进行操作,然后在IDE里面输入"点",却发现什么方法都没有"点"出来,有的IDE能"点"出来东西,只不过都是表达式.此时就需要包装类"大显身手"了:

"程序是对象的集合,它们通过发送消息来告知彼此所要做的.".

包装类是对象,所以可以给它发送消息,也就是调用方法,这些方法可以对它进行多种操作,下面来举几个常用的方法,这里主要以十分常用的Integer为例.

Ingeter.valueOf()与parseInt()

作用:将传入的参数转换为Integer(valueOf())或int(parseInt())并返回.

        String string ="123456";
        System.out.println(Integer.valueOf(1));        //1
        System.out.println(Integer.valueOf(string));   //123456

valueOf()是用来把传入的参数转换为Integer类型的方法,提供了三个版本,这里只看一个参数的两个版本:

   public static Integer valueOf(int i)
   public static Integer valueOf(String s) throws NumberFormatException

一个是传入int,返回值是直接创建一个new Integer(i),传入String的内部调用了另一个静态方法parseInt().

那parseInt()又是何方神圣?看看返回值:

    public static int parseInt(String s, int radix) throws NumberFormatException

返回了int类型,而valueOf返回的是Integer类型,说明valueOf()中又进行了自动装箱,会抛出NumberFormatException,即数字格式异常,容易理解,传入的字符串可能不是规范的int类型整数的格式,此时就无法转换.

xxxValue()与toString()

作用:转换为xxx类型的值并返回,或者转换成字符串内部逻辑都是进行一次类型转换:

    public xxx xxxValue(){
        return (xxx)value;
    }

支持返回所有的数值类型:

public byte byteValue()
public short shortValue()
public int intValue()
public long longValue()
public float floatValue()
public double doubleValue()

转换成字符串就是toString(),许多类都有这个方法,可以方便的展示这个对象的信息.

equals(),compare()与compareTo()

equals():

Integer中的equals()在类型匹配的情况下是直接比较数值: 

    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

所以只要数值相等就返回true.

        int  i = 100;
        Integer i1 =new Integer(100);
        Integer i2 =new Integer(100);
        System.out.println(i1.equals(i2));  //true
        i2 = i;
        System.out.println(i1.equals(i2));  //true

compare():

    public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

x < y 返回-1,相等返回0,x > y返回1,由于自动拆箱与装箱的关系,直接传入int也是可以的:

        int  i = 100;
        Integer i1 = 100;
        Integer i2 = 101;
        Integer i3 = 99;
        System.out.println(Integer.compare(i1, i2)); //-1
        System.out.println(Integer.compare(i1, i));  //0
        System.out.println(Integer.compare(i1, i3)); //1

compareTo():

    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }

调用的是compare(),只需要一个参数,返回结果跟compare()一样,当然只能由Integer对象调用,不能使用int调用,参数是可以传入int类型的:

        int  i = 100;
        Integer i1 = 100;
        Integer i2 = 101;
        Integer i3 = 99;
        System.out.println(i1.compareTo(i2)); //-1
        System.out.println(i1.compareTo(i));  //0
        System.out.println(i1.compareTo(i3)); //1

toXxxString()

转换为对应进制的String类型:

        public static String toBinaryString(int)  //二进制
        public static String toOctalString(int)   //八进制
        public static String toHexString(int)     //十六进制

底层调用的都是toUnsignedString0():

    private static String toUnsignedString0(int val, int shift) {
        int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
        int chars = Math.max(((mag + (shift - 1)) / shift), 1);
        char[] buf = new char[chars];
        formatUnsignedInt(val, shift, buf, 0, chars);
        return new String(buf, true);
    }

第一个参数是要转换的值,第二个参数是2的n次幂进制 (比如4就是 2^4=16进制),是一个private方法,我们不能调用它.

        System.out.println(Integer.toBinaryString(128)); //10000000
        System.out.println(Integer.toOctalString(128));  //200
        System.out.println(Integer.toHexString(128));    //80
        System.out.println(Integer.toHexString(-128));   //ffffff80

其他方法 

sum():对传入的两个数值求和

max():返回传入参数的最大值

min():返回传入参数的最小值

底层调用的都是Math类的同名方法.

       System.out.println(Integer.sum(1000, 900));  //1900
       System.out.println(Integer.max(1000, 900));  //1000
       System.out.println(Integer.min(1000, 900));  //900

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值