Java入门系列之包装类(四)
前言
上一节我们讲解了StringBuilder VS StringBuffer以及二者区别,本节我们来讲解包装类。
包装类
我们知道在Java中有8中基本数据类型,分为数值类型:byte、short、int、long、float、double。字符类型:char。布尔类型:bool,那么什么是包装类呢?包装类是8种基本数据类型的对象表示,而且8种包装类和字符串对象一样是不可变且final(不可通过继承或扩展破坏不可变性)的。我们通过查看int的包装类型Integer可知,如下:
如下为基本数据类型对应的包装类以及构造函数参数:
基本数据类型 | 包装类型 | 构造参数 |
---|---|---|
byte | Byte | byte or String |
short | Short | short or String |
int | Integer | int or String |
long | Long | long or String |
float | Float | float, double or String |
double | Double | double or String |
char | Character | char |
boolean | Boolean | boolean or String |
比如当我们实例化Integer包装类时,既然是对int的包装,要是我们传一个带小数位的数字,毫无疑问也就抛出如下异常了:
public class Main { public static void main(String[] args) {
Integer a = new Integer("12.5");
}
}
开头我们就直接抛出了包装类的概念,但是不知道您是否有和我一样的疑惑,我们为什么要用包装类呢?比如Integer是对int的包装,我们直接使用int不就完事了吗,怎么还包装一层呢?这就需要我们了解包装类的作用是什么了?
1.包装类将基本数据类型转换为对象(当我们需要在给定方法中传递参数时需要对象)。
2.包java.util只处理对象的类,所以包装类在这个包中也有其用武之地。
3.数据结构仅存储对象和基本数据类型。
4.在多线程中,我们需要对象来支持线程同步。
或者说存在即合理,在Java中将包装类和基本数据类型区分开这是明智之举,当我们以适合面向对象的方式编程时,我们使用包装类,当处理起来更加简单时,我们使用基本数据类型,一切取决于我们。
自动装箱和拆箱
在Java 5中引入了自动装箱和拆箱,这允许基本数据类型和包装类相互之间能够轻松自如的实现转换。接下来我们通过基本数据类型和包装类转换实现装箱和拆箱,装箱则是自动将基本数据型转换为包装类,拆箱反之。
char ch = 'a';
Character a = ch; ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(25);
System.out.println(arrayList.get(0));
如上第一个我们将基本数据类型转换为对象以及我们初始化集合且参数类型为包装类(对象),紧接着我们在此集合中添加基本数据类型为25的int,都自动实现了装箱。反过来,如下我们将实现拆箱:
Character ch = 'a';
char a = ch;
ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(24);
int num = arrayList.get(0);
System.out.println(num);
上述我们首先将包装类转换为基本数据类型,紧接着我们添加基本数据类型为24的int,这属于装箱,但是最后我们获取数据时赋值给为int的num,也就达到了将包装类到基本数据类型的转换,也就是拆箱。同时我们还需谨记:包装类可以为空,基本数据类型不能为空。也就是说要使其可空,我们必须使用包装类,这一点比不上C#语法高级,若基本数据类型可空,在C#中可如下定义:
int? a = null;
Console.WriteLine(a == null);
接下来我们来看如下一道题,请问:如下是自动装箱吗?如果不是体现了什么呢?
public class Main { public static void main(String[] args) { char c = 'a'; doSomething(new Character(c));
} static void doSomething(Object obj) { } }
我们知道自动装箱是将基本数据类型转换为包装类,上述我们定义了一个doSomething方法,参数为Object类型,在程序入口点,我们调用该方法且传入的参数为包装类,所以上述并不是自动装箱,它所体现的是通过包装类实现多态。所以我们需谨记:自动装箱是将基本数据类型转换为包装类,而不是将一种数据类型转换为其他数据类型,这也许就是为什么自动装箱不能将String转换为包装类的原因。
数据类型转换
我们依然以基本数据类型int为例,在int对应的包装类Integer中有intValue方法实现拆箱,比如我们想要将double转换为int,利用包装类实现则是如下形式:
double d = 135.d;
Double doubleWrapper = new Double(d);
int integerValue = doubleWrapper.intValue();
System.out.println(integerValue);
我们也可以使用包装类类型通过拆箱转换成其他基本数据类型,当我们需要将基本数据类型转换为对象并使用它们来获取其他基本数据类型时,将使用这种类型的转换。通过如上转换,我们需要编写一大片代码, 然而,我们可以通过如下简单的方式来实现相同的目的:
double d = 135.d;
int integerValue = (int)d;
System.out.println(integerValue);
valueOf和parseInt使用详解
到目前我所知道的有以下两种方式将String对象转换为int或Integer,我们一起来看看。
Integer.parseInt
此种方式作为将String转换为int的首先方式,简单且灵活,我们看一个例子:
int i = Integer.parseInt("123");
System.out.println("i: " + i);
如果提供的String不是正确的数字,Integer.parseInt()方法将抛出NumberFormatException异常,相同的方式同样适用于其他数据类型(如float和Double)转换为Java中的String。 Java API提供静态方法,如Float.parseFloat()和Double.parseDouble(),以执行数据类型转换。
Integer.valueOf
在8种包装类中都有这个valueOf方法,这也是一种将String转换为int的方式,我们同样来看一个示例:
int i = Integer.valueOf("000000081");
System.out.println("i: " + i);
它将忽略前导零并将字符串转换为int。如果提供的String不是正确的数字,同样也会抛出NumberFormatException异常。在Java 1.4之前没有自动装箱,但是在Java 1.5即(Java 5+)引入了自动装箱,所以推荐使用Integer.valueOf(int)而不是new Integer(int),因为Integer现在可以在-128到127之间缓存Integer对象,并且每次都可以将同一个完整的Integer(0)对象交给我们,而不是在全新的相同Integer对象上浪费对象构造。
下面我们来看两个例子来验证上述源码观点:
Integer i1 = 260;
Integer i2 = 260;
if (i1 == i2) {
System.out.println("i1 and i2 is equal");
} else {
System.out.println("i1 and i2 is not equal ");
}
接下来我们再来看一个例子,如下:
Integer i1 = 100;
Integer i2 = 100;
if (i1 == i2) {
System.out.println("i1 and i2 is equal");
} else {
System.out.println("i1 and i2 is not equal ");
}
我们看到“i1和i2相等”,因为-128到127之间的int值在大多数JVM要缓存的范围内,所以VM实际上对i1和i2使用相同的对象实例(因此也使用同一内存地址),所以打印出相等。Integer.valueOf方法还有重载,我们来看一个例子:
Integer I = Integer.valueOf("100", 2);
System.out.println(I);
Integer i = Integer.valueOf("101", 4);
System.out.println(i);
第二个参数表示进制,例如上述两个通过2进制表示100,通过4进制表示101,计算方式如下:
2进制表示100:(1 * 2 ^ 2)+(0 * 2 ^ 1)+(0 * 2 ^ 0)= 4 + 0 + 0 = 4。 4进制表示101:(1 * 4 ^ 2)+(0 * 4 ^ 1)+(1 * 4 ^ 0)= 16 + 0 + 1 = 17。
总结
valueOf和parseInt方法都用于在Java中将String转换为Integer,但它们之间存在细微差别(在Java 1.5引入自动装箱后),我们通过查看valueOf()方法的源码得知,发现它在内部调用parseInt()方法将String转换为Integer,但是它还维护一个从-128到127的整数池,如果请求的整数在池中,它从池中返回对象,这也意味着使用valueOf()方法返回的两个整数对象可以通过相等运算符相同,这种对不可变对象的缓存,确实有助于减少垃圾并帮助垃圾收集器。 parseInt()和valueOf()方法之间的另一个区别是返回类型,valueOf()返回一个Integer对象,而parseInt()方法返回一个int基本数据类型。无论是使用parseInt还是valueOf将String转换为基本数据类型Int和包装类Integer,如果我们需要基本数据类型Int可以使用parseInt,由于不可变对象可以安全地缓存在池中并且得到重用,如此一来减少了垃圾收集器的负载,因此如果需要Integer对象,最好使用valueOf。
Java中的“==”或等于运算符是Java编程语言提供的二元运算符,用于比较基元和对象,在比较boolean,int,float等基本数据类型时,利用“==”工作正常,但在比较对象时,它会与Java中的equals方法产生混淆, “==”根据内存引用比较两个对象。 所以“==”运算符只有在两个对象引用比较时才返回true来表示完全相同的对象,否则“==”将返回false。在Java 5中引入自动装箱和拆箱之后,因版本的问题使用“==”来比较包装器对象可能会出现意想不到的结果。
Java入门系列之包装类(四)的更多相关文章
- Java NIO系列教程(四) Scatter 和 Gather
Java NIO系列教程(四) Scatter 和 Gather Java NIO 开始支持 scatter/gather,scatter/gather 用于描述从 Channel(译者注:Chann ...
- Java 设计模式系列(十四)命令模式(Command)
Java 设计模式系列(十四)命令模式(Command) 命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复 ...
- 数据挖掘入门系列教程(四)之基于scikit-lean实现决策树
目录 数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iris 加载数据集 数据特征 训练 随机森林 调参工程师 结尾 数据挖掘入门系列教程(四)之基于scikit-lean决策树处理 ...
- Java入门系列-19-泛型集合
集合 如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足. 如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架. Java 集合框架提 ...
- Java入门系列 泛型
前言 <Java编程思想>第四版足足用了75页来讲泛型——厚厚的一沓内容,很容易让人头大——但其实根本不用这么多,只需要一句话:我是一个泛型队列,狗可以站进来,猫也可以站进来,但最好不要既 ...
- Java入门系列-26-JDBC
认识 JDBC JDBC (Java DataBase Connectivity) 是 Java 数据库连接技术的简称,用于连接常用数据库. Sun 公司提供了 JDBC API ,供程序员调用接口和 ...
- Java入门系列 Java 中的四种引用
Why java内存管理分为内存分配和内存回收,都不需要程序员负责,垃圾回收的机制主要是看对象是否有引用指向该对象. java对象的引用包括强引用,软引用,弱引用,虚引用 Java中提供这四种引用类型 ...
- Java入门系列(四)内部类
为什么需要内部类? 真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题没有多继承.实际上,C++的多继承设计起来很复杂,而java通过内部类加 ...
- Java入门系列之集合HashMap源码分析(十四)
前言 我们知道在Java 8中对于HashMap引入了红黑树从而提高操作性能,由于在上一节我们已经通过图解方式分析了红黑树原理,所以在接下来我们将更多精力投入到解析原理而不是算法本身,HashMap在 ...
随机推荐
- 跟着文档学习gulp1.1安装入门
Step1:检查是否已经安装了node,npm 和 npX是否正确安装 Step2:安装gulp命令行工具(全局安装gulp) npm install --global gulp-cli Step3: ...
- 两个div,都设置未inline-block,可是在IE出现错位问题
[实现要求] 红色的和黄色的内容撑开,蓝色包住红黄,不定框居中显示 [遇到问题] chrome显示正常,但是在IE上红黄框会出现错位的问题 [如何解决] 给红色框添加一个overflow:hidde ...
- .Net C# 时间戳时间转换
闲话不多说,直接上代码 /// <summary> /// 时间拓展 /// </summary> public static class DateTimeExtension ...
- springmvc源码学习
1.springmvc运行流程 流程图是直接在百度图片中找的一张 >.前台发送请求,请求会首先通过DispatcherServlet进行url的匹配;如果匹配不到,看是否配置<mvc: ...
- css重点知识和bug解决方法
1.图片向下撑大3像素问题 在一个盒子里面放一张图片,默认情况下,图片会向下撑大3像素,有以下几种解决方法: 1.1 给图片添加display:block: 1.2 给图片添加 float:left: ...
- POJ2182题解——线段树
POJ2182题解——线段树 2019-12-20 by juruoOIer 1.线段树简介(来源:百度百科) 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线 ...
- PWN INTEGER OVERFLOW 整数溢出
0x00 Preview Last few passage I didn't conclude some important points and a general direction o ...
- Winform中使用Timer实现滚动字幕效果(附代码下载)
场景 效果 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 新建一个Fo ...
- vue-practice
vue-完整代码 这是一个完整的vue案例,但是接口似乎都失效了,单是代码本身还是很有参考价值的呦!~ 里面包含了:vue,vue-router,....,还是直接看json文件吧 { "n ...
- 拥抱微服务,CODING 即将上线单项目多仓库功能
随着数字化时代的全面到来,越来越多的企业开始尝试物联网.人工智能等新兴技术,用以加快自身的转型速度并积极开拓新的市场.互联网的兴起让各个行业的业务场景.用户行为.交互方式等都发生了巨大的变化.线上业务 ...