初始化块
是构造器的补充,在构造器之前执行。
是一段固定的代码,不接受任何参数。
构造器其实是一个假象,编译Java类后,初始化块会消失,当中的代码被还原到构造器中,且位于构造器前面。
静态初始化块
用 static 修饰,属于类的静态成员,不能访问非静态成员。
package com.ittht.day06;
class Root{
static {
System.out.println("Root中的静态初始化块");
}
{
System.out.println("Root中的普通初始化块");
}
public Root(){
System.out.println("Root中的无参构造器");
}
}
class Mid extends Root{
static {
System.out.println("Mid中的静态初始化块");
}
{
System.out.println("Mid中的普通初始化块");
}
public Mid(){
System.out.println("MId中的无参构造器");
}
public Mid(String ch){
this();
System.out.println("Mid中的带参构造器,其中的参数:"+ch);
}
}
class Leaf extends Mid{
static {
System.out.println("Leaf中的静态初始化块");
}
{
System.out.println("Leaf中的普通初始化块");
}
public Leaf(){
super("java");//使用super显式调用父类的构造器
System.out.println("执行Leaf中的构造器");
}
}
public class Test {
public static void main(String[] args) {
new Leaf();
}
}
输出结果为:
Root中的静态初始化块
Mid中的静态初始化块
Leaf中的静态初始化块
Root中的普通初始化块
Root中的无参构造器
Mid中的普通初始化块
MId中的无参构造器
Mid中的带参构造器,其中的参数:java
Leaf中的普通初始化块
执行Leaf中的构造器
编译时,要执行其父类的静态初始化块,一直上溯至 java.lang.Object 类(如果有静态初始化块),执行其的静态初始化块,最后才执行该类的静态初始化块。
然后对于普通初始化块,是在构造器之前执行,也是上溯至 java.lang.Object 类(如果有普通初始化块或者构造器),先执行它的初始化块,然后执行它的构造器……最后才执行该类的普通初始化块和构造器。
Java 系统加载并初始化某个类时,总是保证该类的所有父类(包括直接父类和间接父类)全部加载并初始化。
声明和静态初始化块
package com.ittht.day06;
public class StaticInitTest {
static {
a=9;//语句1
}
static int a=10;//语句2
public static void main(String[] args) {
System.out.println(StaticInitTest.a);
}
}
其中语句 1 代表的是静态初始化块,语句 2 代表的是声明,当前代码输出的为 10。
但是交换语句 1 和语句 2 的位置,输出的值会变化。
这是因为静态初始化块和声明变量指定的初始值都是该类的初始化代码,它们的执行顺序与源程序中的顺序有关。
当 JVM 第一次主动执行某类时,系统会在类准备阶段为该类的所有静态成员变量分配内存;在初始化阶段则负责初始化这些静态成员变量,初始化静态成员变量就是执行类初始化代码或声明类变量时指定的初始值,他们的执行顺序与源代码中的排序相同。
包装类
包装类是将基本数据类型首字母大写,只有 int 和 char 特殊一些,int 对应的是 Integer,char 对应的是 Character。
自动装箱:把一个基本数据类型变量直接赋给对应的包装类变量,或者直接赋值给 Object 变量。(Object 类是所有类的父类,子类对象可以直接赋给父类变量)
自动拆箱:允许直接把包装类对象赋给一个对应的基本数据类型变量。
package com.ittht.day06;
public class AutoBoxingUnboxing {
public static void main(String[] args) {
//把一个基本数据类型赋给Integer对象
Integer in=5;
//直接把一个boolean类型变量赋给Object类型的变量
Object ob=true;
//把一个Integer变量赋给int类型的变量
int it=in;
if(ob instanceof Boolean)//判断转换能不能实现
{
//把Object对象强制转换为Boolean类型,再赋给boolean(有先后)
boolean oc=(boolean) ob;
System.out.println(ob);
}
}
}
对于包装类的作用还不是很清楚,所以去查了一下:
- 集合只能存放引用数据类型,不能存放基本数据类型,如 add(Object o)
- 基本数据类型和包装类可以互相转换(自动装箱拆箱)
- 包装类的 parse 方法可以实现基本数据类型+string 类型的相互转换
- 函数需要传递进去的参数为 Object 类型,传入基本数据类型不行
把字符串类型转换为基本类型的值:
- 利用包装类提供的 parseXxx(String s)静态方法(除 Character 之外的所有包装类都提供了该方法)
- 利用包装类提供的 valueOf(String s)静态方法
将基本数据类型转换为字符串:
- String.valueOf(primitive) 转换
- 在基本数据类型后+“”,会自动转换为字符串
package com.ittht.day06;
public class Primitive {
public static void main(String[] args) {
//把字符串类型转换成基本数据类型
String str1="123";
int it1=Integer.parseInt(str1);
int it2=Integer.valueOf(str1);
System.out.println(it1);
System.out.println(it2);
String str2="5.69";
float ft1=Float.parseFloat(str2);
float ft2=Float.valueOf(str2);
System.out.println(ft1);
System.out.println(ft2);
//把基本数据类型转换成字符串类型
String ftStr=String.valueOf(2.25f);
String dtStr=String.valueOf(8.33);
System.out.println(ftStr);
System.out.println(dtStr);
}
}