java 怎么把list 中string转换成integer_Java核心技术深入讲解:对象包装器与自动打包,原来可以这么理解...

对象包装器与自动打包

有时,需要将int这样的基本类型转换为对象。所有的基本类型都有一个与之对应的类。例如,Integer类对象基本类型int。通常,这些类称为包装器(wrapper)。这些对象包装器类拥有很鲜明的名字:Integer、Long、Float、Double、Short、Byte、Character、Void和Boolean。(前6个类派生于公共的超类Number。)对象包装器类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值。同时,对象包装器类还是final的,因此不能定义它们的子类。

假设想定义一个整型数组列表。而尖括号中的类型参数不允许是基本类型,也就是说,不允许写成ArrayList。这里就用到了Integer对象包装器类。我们可以声明一个Integer对象的数组

列表。

ArrayList<Integer> list = new ArrayList<Integer>( );

885c409a18aa0bb3fa519bc2cf736b4c.png

警告:由于每个值都分别包装在对象中,所以ArrayList的效率远远低于int[ ]数组。

因此,应该用它构造小型集合,因为在此时,程序员操作的方便性要比执行效率更加重要。

JDK 5.0的另一个改进是更加便于添加或获取数组元素。下面这个调用:

list.add(3);

将自动地变换成

list.add(new Integer(3));

这种变换被称为自动打包(autoboxing)。

注意:大家可能认为自动打包(autowrapping)更加合适,而“装箱”(boxing)这个词源自于C#。

相反,当将一个Integer对象赋给一个int值时,将会自动地拆包。也就是说,编译器将下列语句:

int n = list.get(i);

翻译成

int n = list.get(i).intValue( );

甚至在算术表达式中也能够自动地打包和拆包。例如,可以将自增操作符应用于一个包装器引用:

Integer n = 3;

n++;

编译器将自动地插入一条拆开对象包的指令,然后进行自增计算,最后再将结果打入对象包内。

在很多情况下,容易有一种假象,即基本类型与基对象包装器是一样的,只是它们的相等性不同。大家知道,==运算符也可以应用于对象包装器对象,只不过检测的是对象是否指向同一个存储区域,因此,下面的比较通常不会成立:

Integer a = 1000;

Integer b = 1000;

if (a == b) . . .

然而,Java实现却有可能(may)让它成立。如果将经常出现的值包装到同一个对象中,那么这种比较就有可能成立。这种不确定的结果并不是我们所希望的。如果在两个包装器对象进行比较时,调用equals方法不会出现这个问题。

注意:自动打包规范要求boolean、byte、char≤127,介于-128~127之间的short和int被包装到固定的对象中。例如,如果a和b在前面的例子中被初始化为100,那么对它们进行比较,其结果一定是成立的。

最后强调一下,打包和拆包是编译器认可的,而不是虚拟机。编译器在生成类的字节码时,插入必要的方法调用。虚拟机只是执行这些字节码。

自JDK 1.0开始就存在包装器类,但是在JDK 5.0之前,必须手工地插入打包和拆包的代码。

使用数值对象包装器还有另外一个好处。Java设计者发现,可以将某些基本方法放置在包装器中,例如,将一个数字字符串转换成数值。

要想将字符串转换成整型,可以使用下面这条语句:

int x = Integer.parseInt(s);

这里与Integer对象没有任何关系,parseInt是一个静态方法。但Integer类是放置这个方法的一个好地方。

API注释说明了Integer类中包含的一些重要方法。其他数值类也实现了相应的方法。

ade3186c5c1ee2914d3660bddf131618.png

警告:有些人认为包装器类可以用来实现修改数值参数的方法,然而这是错误的。在第4章中曾经讲到,由于Java方法都是值传递,所以不可能编写一个下面这样的能够增加整型参数值的Java方法。

public static void triple(int x) //won't work{x = 3 * x; //modifies local variable}

将int替换成Integer又会怎样呢?

public static void triple(Integer x) //won't work{. . .}

问题是Integer对象是不可变的:包含在包装器中的内容不会改变。不能使用这些包装器类创建修改数值参数的方法。

注意:如果想编写一个修改数值参数值的方法,就需要使用在org.omg.CORBA包中定义的持有者(holder)类型,包括IntHolder、BooleanHolder等等。每个持有者类型都包含一个公有(!)域value,通过它可以访问存储在其中的值。

public static void triple(IntHolder x){x.value = 3 * x.value;}

java.lang.Integer 1.0

• int intValue( )

以int的形式返回Integer对象的值(在Number类中覆盖了intValue方法)。

• static String toString(int i)

以一个新String对象的形式返回给定数值i的十进制表示。

• static String toString(int i,int radix)

返回数值i的基于给定radix参数进制的表示。

• static int parseInt(String s)

返回字符串s表示的整型数值,假设给定字符串表示的是十进制的整数。

• static int parseInt(String s,int radix)

返回字符串s表示的整型数值,假设给定字符串表示的是基于给定radix参数进制的整数。

• static Integer valueOf(String s)

返回用整型数值进行初始化后的一个新Integer对象,假设给定的String表示的是一个十进制整型数值。

• static Integer value Of(String s,int radix)

返回用整型数值进行初始化后的一个新Integer对象,假设给定的String表示的是一个基于给定radix参数进制的整数。

java.text.NumberFormat 1.1

• Number parse(String s)

返回数字值,假设给定的String表示了一个数值。

参数数量可变的方法

在JDK 5.0以前的版本中,每个Java方法都有固定数量的参数。然而,现在的版本提供了可以用可变的参数数量调用的方法。(有时称为“可变参”方法。)

前面已经看到过这样的方法:printf。例如,下面的方法调用:

System.out.printf("%d", n);

System.out.printf("%d %s", n, "widgets");

上面两条语句尽管一个调用中包含两个参数,另一个调用包含三个参数,但它们调用的都是同一个方法。printf方法是这样定义的:

public class PrintStream{public PrintStream printf(String fmt,Object. . . args) {return format(fmt, args);}}

这里的省略号. . .是Java代码的一部分,它表明这个方法可以接收任意数量的对象(除fmt参数之外)。

实际上,printf方法接收两个参数,一个是格式字符串,另一个是Object[ ]数组,其中保存着所有的参数。(如果调用者提供的是整型数组或者其他基本类型的值,自动打包功能将把它们转换成对象。)现在将扫描fmt字符串,并将第i个格式说明符与args[i]的值匹配起来。

换句话说,对于printf的实现者来说,Object. . .参数类型与Object[ ]完全一样。

编译器需要对printf的每次调用进行转换,以便将参数绑定到数组上,并在必要的时候进行自动打包:

System.out.printf("%d %d", new Object[ ] { new Integer(d), "widgets"});

用户自己也可以定义可变参数的方法,并将参数指定为任意类型,甚至是基本类型。下面是一个简单的例子:其功能为计算若干个数值的最大值。

public static double max(double. . . values){double largest = Double.MIN_VALUE;for (double v : values) if (v > largest) largest = v;return largest;}

可以像下面这样调用这个方法:

double m = max(3.1, 40.4, -5);

编译器将new double[ ] {3.1, 40.4, -5}传递给max方法。

注意:允许将一个数组传递给可变参数方法的最后一个参数。例如:

System.out.printf("%d %s", new Object[ ]{new Integer(1), "widgets"});

因此,可以将已经存在且最后一个参数是数组的方法重新定义为可变参数的方法,而不会破坏任何已经存在的代码。例如,MessageFormat.format在JDK 5.0就采用了这种方式。

觉得文章不错的话,可以转发一下关注小编,明天更新反射的内容,大家到时候来围观!!!

e91ca4abe11af630ccd2f7e52df9d18c.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值