Java基本类型与引用类型
基本类型(primitive type)
- boolean 不同于C语言Java在JVM实现中用整形0 1表示。JVM对整形指令做了优化。
- "位"用0和1来表示 ,true的值在内存中就表示1,false在内存中就是表示0。
- 不同于int的0和1,一个int型的变量,占用的内存空间是4个字节,4*8 位
- char前256个表示特殊字符; 字符常量为用单引号括起来的单个字符,例如: char c = 'A'; char i=97;
- java字符采用Unicode编码,可用十六进制编码形式表示。 char c1 = '\u0061';
- 在字符的操作中还存在着转义字符。例如:换行符\n,制表符\t,回车符\r,双引号\",反斜杠\\,单引号\'
- 整数型: byte、short、 int、long Java语言整型常量的四种表示形式: 二进制整数,0b或0B开头,如:int a=0B110; 十进制整数,默认类型 八进制整数,要求以0开头,如 int a = 012; 十六进制整数,要求0X或0x开头,如int b = 0x12;
- byte,short,char → int → long → float → double
- byte,short,char之间不会相互转换,他们在计算时首先会转换为int类型。 基本数据类型转换之——向下转型
- 容量大的数据类型转换为容量小的数据类型时,要加上强制转换符,但可能 造成精度的降低或溢出,使用时要格外注意。
- 有多种类型的数据混合运算时,系统首先自动的将所有数据转换成容器最 大的数据类型,再计算。
- 浮点数型: float、 double(默认) double和float并不能表示一个精确的数字; 两种表示方式:
- 十进制形式: 例如:3.14 ,168.0, .618
- 科学计数法形式: 例如:3.14e2, 3.14E2,
- 要声明一个常量为float型,则需在常 量后加上f 或 F或转型 float pi3 = (float)3.14;
基本类型的引用类型
简介
原始类型 |
byte |
short |
int |
long |
char |
float |
double |
boolean |
引用类型 |
Byte |
Short |
Integer |
Long |
Character |
Float |
Double |
Boolean |
引用类型说明
- 除了Integer和Character定义的名称和对应的基本类型差异大,其他六种都是将首字母大写就可以了。
- Integer,Byte,Float,Double,Short,Long都是Number类的子类。(Number类后面讲);
- Character和Boolean都是Object直接子类;
- 8个类都是final修饰的(不可被继承)。
- 引用类型,内部维护一个对应基本类型数据引用。自动转换是通过调用自身引用。所以要避免引用类型为null,空对象不能调用自身属性和方法。保存引用是需要占内存的,这个机器的寻址空间有关。通常java在32/64位操作系统都占4字节。原因是64为操作系统开启了指针压缩。
基本数据类型和包装类相互转换
-
把基本数据类型 → 包装类:
- 通过对应包装类的构造方法实现
- 除了Character外,其他包装类都可以传入一个字符串参数构建包装类对象。
-
包装类 → 基本数据类型
- 包装类的实例方法xxxValue(); // xxx表示包装类对应的基本数据类型
基本类型和String之间的转换
- String → 基本类型,除了Character外所有的包装类提供parseXxx(String s)静态方法,用于把一个特定的字符串转换成基本类型变量;
- 基本类型 → String,String 类有静态方法valueOf(),用于将基本类型的变量转换成String类型。
默认值
引用类型默认值为null,null 作为值可以赋值给任意引用类型
原生类型,这里避免引用类型null赋值
在做数学运算时所有的number类型符合数学运算性质,无论是否是同一类型。如:3L==1+2;
优先使用基本类型,除了引用类型占用更多的内存外,隐式的拆箱可能会有空指针问题,在性能上引用类型也差很多。在使用基本类型的引用数据类型时,一定要时刻注意引用类型是个对象,方法中含有引用类型参数时,它可能表示一个成员。避免隐式的自动装箱把一个成员对应的序号转成成员值。如:删除一个Integer成员,自动拆箱把它翻译为一个序号,这个删除的是序号对应的另一个成员。
数字判断
自动装箱参数的设计问题
引用数据类型
接口、数组、类实例都是引用类型。其中数组和类实例是对象。null是任何引用类型的默认值,严格的说是所有Object类型(类、接口、数组等)的默认值。java中的任何引用变量都将null作为默认值。在使用没有初始化的局部变量,编译器会提示初始化。null既不是对象也不是一种类型,它仅是一种特殊的值,你可以将其赋予任何引用类型,你也可以将null转化成任何类型。
null是Java中一个很重要的概念。null设计初衷是为了表示一些缺失的东西,例如缺失的用户、资源或其他东西。
你可能知道不能调用非静态方法来使用一个值为null的引用类型变量。它将会抛出空指针异常,但是你可以用一个值为null的引用类型使用静态方法。因为每个类东西都隐含指向类class对象,通过class对象调用静态方法,索引不会抛出空指针异常。这种间接调用类属方法并不推荐。关于静态方法你可以参考这篇文章,或者在后面学习。下面是一个例子:
数组
在内存中申请一块连续的地址块,保存同一种类型数据的集合,元素个数和每个元素占用内存固定。数组里的每个元素都有下标,编号从0开始;依次递增。
数组的数据结构非常节省内存,引用只需要保存内存块的其实地址,根据类型占用内存计算可以获取目标元素,这样也避免了内存寻址,非常快速。
- 效率,数组是一种效率最高的存储和随机访问对象引用序列的方式。数组就是一个简单的线性序列,这使得元素访问非常快速。
- 数组标识符是一个引用指向在堆中的一个对象,保存指向其他数组成员对象的引用。只读成员length表示此数组对象可以存储多少元素。"[]"语法是访问数组对象的唯一方式。
- 数组与泛型,数组要求元素是确定的,所以不能是参数类型,数组对象用一个标示表示是哪种类型的数组,你可以在参数中使用T[],表示T泛型数组,在传参数过程其实是确定的。
数组声明
静态初始化:初始化数组时已经指定数据集合
上面写法是一种推荐简写,下面是标准写法。
动态初始化:指定数据类型和长度,在需要是赋值。
多维数组
操作数组的工具类-Arrays
常用方法:
static int binarySearch(type[] a, type key) 使用二分搜索法来搜索key元素在
static boolean equals(type[] a, type[] a2) 如果两个数组长度相等和元素一一相等,则返回 true
static void sort(type[] a) //sort(int[] arr)对指定的数组按数字升序进行排序。
static String toString(type[] a) 返回指定数组内容的字符串表示形式。多个数组元素之间用英文逗号或空格隔开。
操作数组的工具类-System
使用java.lang.System类public static void arraycopy(Object src,int srcPos,Object dest, int destPos,int length):数组src从第srcPos项元素开始的length个元素拷贝到目标数组dest从destPos开始的length个元素。
- src - 源数组。
- srcPos - 源数组中的起始位置。
- dest - 目标数组。
- destPos - 目标数据中的起始位置。
- length - 要复制的数组元素的数量。
引用类型
String
String 与StringBuffer、StringBuilder:三个字符串对象
这会在字符串常量池中产生3个字符串对象:ja、va、java。
针对这个问题,用StringBuilder、StringBuffer的方法拼接字符串会产生一个对象,StringBuffer是线程安全的。一般建议用StringBuilder
主动引用
引用类初始化的5种条件:
- new 关键字实例化对象、读取或设置类的静态字段、调用类的静态方法
- 反射调用
- 初始化父类
- Jar包等类似,main方法为入口的类
-
动态语言
除此之外都不会触发类初始化。(类并不是对象)
被动引用
这里可以看到类只有在用子类时子类初始化了,其它都没有触发初始化。这是jvm的优化。
接口
接口引用不会触发所有父接口初始化,只有用到的接口初始化。
反编译后的结果。(跟这个有关系吗?)