JAVA基础(2)——数据类型

JAVA基础系列规划:


JVM将数据类型可以分为两类:

  • 基本类型。变量保存原始值,即遍历代表的值就是数值本身;
  • 引用类型。变量保存引用值。“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放在这个引用值所表示的地址的位置。

1. 基本类型

基本类型包括:byte, short, int, long, char, float, double, Boolean。

具体字面意思参考Oracle文档

基本类型之间的转换

将一种类型的值赋给另一种类型是很常见的。在Java中,boolean类型与所有其他7种类型都不能进行转换,这一点很明确。对于其他7中数值类型,它们之间都可以进行转换,但是可能会存在精度损失或者其他一些变化。转换分为自动转换和强制转换。对于自动转换(隐式),无需任何操作,而强制类型转换需要显式转换,即使用转换操作符(type)。首先将7种类型按下面顺序排列一下:
byte <(short=char)< int < long < float < double
如果从小转换到大,可以自动完成,而从大到小,必须强制转换。short和char两种相同类型也必须强制转换。

2. 引用类型

引用类型包括:类类型,接口类型,数组和null。

2.1 类类型

类类型变量不同于基本类型变量存储值的方式。不管是基本变量还是类类型变量,都实现为一个内存位置。但是,由于基本变量所需的内存数量是相同的,所以系统可以给它设置一个固定的空间保持命名对象的变量。类类型变量则不同,由于它的长度不确定,从而使得系统难以给其分配一个固定的空间来保存命名对象的变量。因此,对于类类型变量,它存储的是对象的内存地址,而不是对象本身。

String、StringBuffer、StringBuilder

String和StringBuffer是最早的字符串容器,从jdk1.0开始就已存在。StringBuilder从jdk1.5开始出现。

String

扫描二维码关注公众号,回复: 2010304 查看本文章

从String源码可以看到:

  • String是final类,表明了String类是不可继承的,并且默认它的成员方法都final方法。使用final,一方面是为了锁定方法,另一方面在早期版本中jvm会将final方法转为内嵌调用以提升效率,但从jdk1.6开始淡化这种转换。因此在现在的Java SE版本中,不需要考虑用final去提升方法调用效率。只有在确定不想让该方法被覆盖时,才将方法设置为final。
  • String实现了Serializable、Comparable、CharSequence,因此可序列化、可比较、可进行char数组操作。
  • String类通过final修饰的char数组来保存字符串的,因此value不可变。
  • String内部的change操作都会生成新的对象,因此对String对象的任何改变都不影响到原对象。

StringBuffer

从StringBuffer源码可以看到:

  • StringBuffer是final类,表明了StringBuffer类是不可继承的,并且默认它的成员方法都final方法。
  • StringBuffer继承AbstractStringBuilder,实现Serializable、CharSequence。AbstractStringBuilder实现了Appendable、CharSequence,动态维护char数组的大小,并通过append等方法进行字符串追加。StringBuffer的方法都只是对AbstractStringBuilder方法的简单synchronized封装。

StringBuilder

从StringBuilder源码可以看到:

  • StringBuilder是final类,表明了StringBuilder类是不可继承的,并且默认它的成员方法都final方法。
  • StringBuilder继承AbstractStringBuilder,实现Serializable、CharSequence。AbstractStringBuilder实现了Appendable、CharSequence,动态维护char数组的大小,并通过append等方法进行字符串追加。和StringBuffer类似的区别在于StringBuilder是非线程安全的。

总的来说,三者内部都维护着char数组,区别在于:

从线程安全性上来看,String和StringBuffer是线程安全的。String是不可变的,每次更新操作都产生新的对象,因此线程安全。StringBuffer通过对方法加同步锁实现线程安全。StringBuilder内部char数组可变,同时方法未加同步锁,因此非线程安全。

从性能上来说,每次对String类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象。StringBuffer每次都会对 StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder相比使用StringBuffer仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

2.2 接口类型

2.3 数组

数组是一种高效的存储和随机访问对象引用序列的方式,使用数组可以快速的访问数组中的元素。但是当创建一个数组对象(注意和对象数组的区别)后,数组的大小也就固定了,当数组空间不足的时候就再创建一个新的数组,把旧的数组中所有的引用复制到新的数组中。

在操作数组时需要进行边界检查,如果越界就会得到一个RuntimeException异常。一般情况下,考虑到效率与类型检查,应该尽可能考虑使用数组。如果要解决一般化的问题,数组可能会受到一些限制,这时可以使用Java提供的容器类。

在java.util.Arrays类中,有许多static静态方法,主要实现数组的排序、复制等功能。通常我们会使用Arrays.asList来生成一个List,这个List是Arrays里面的静态类Arrays.ArrayList,Arrays.ArrayList和ArrayList的最大区别在于Arrays.ArrayList维护的是E[]数组,而ArrayList维护的是Object[]数组。因此要特别注意Arrays.ArrayList.toArray和ArrayList.toArray获取的数组类型是不一样的。

2.4 null

null是一种特殊的type,但是你不能声明一个变量为null类型,null type的唯一取值就是null。null可以负值给任意的引用类型或者转化成任意的引用类型。在实践中,一般把null当做字面值(literal),这个字面值可是是任意的引用类型。

猜你喜欢

转载自blog.csdn.net/weitry/article/details/53292723