引言:
Java中类的成员除了常用的属性、方法、构造器以外,还有代码块和内部类。其中代码块主要是用来做一些初始化的工作。
代码块的作用:用来初始化类、对象
代码块如果有修饰的话,只能使用static.
分类:静态代码块 and 非静态代码块
静态代码块
- 内部可以有输出语句
- 随着类的加载而执行(注:静态方法随着类的加载而加载),而且只执行一次
- 作用:初始化类的信息
- 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
- 静态代码块的执行要优先于非静态代码块的执行
- 静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构
非静态代码块
- 内部可以有输出语句
- 随着对象的创建而执行,且比构造器先执行
- 每创建一个对象,就执行一次非静态代码块
- 作用:可以在创建对象时,对对象的属性等进行初始化
- 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
- 非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法
java类中的常用结构:
public class BlockTest {
public static void main(String[] args) {
String desc = Person.desc;
System.out.println(desc);
Person p1 = new Person();
Person p2 = new Person();
System.out.println(p1.age);
Person.info();
}
}
class Person{
//非静态属性
String name;
int age;
//静态属性
static String desc = "我是一个人";
//空参构造器
public Person(){
}
//带参构造器
public Person(String name,int age){
this.name = name;
this.age = age;
}
//非static的代码块
{
System.out.println("hello, block - 2");
}
{
System.out.println("hello, block - 1");
//调用非静态结构
age = 1;
eat();
//调用静态结构
desc = "我是一个爱学习的人1";
info();
}
//static的代码块
static{
System.out.println("hello,static block-2");
}
static{
System.out.println("hello,static block-1");
//调用静态结构
desc = "我是一个爱学习的人";
info();
//不可以调用非静态结构
// eat();
// name = "Tom";
}
//非静态方法
public void eat(){
System.out.println("吃饭");
}
//方法的重写(覆盖)
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
//静态方法
public static void info(){
System.out.println("我是一个快乐的人!");
}
}
由父及子,静态先行:
class Root{
static{
//step_1
System.out.println("Root的静态初始化块");
}
{
//step_4
System.out.println("Root的普通初始化块");
}
public Root(){
super();//默认调用父类空参构造器
//step_5
System.out.println("Root的无参数的构造器");
}
}
class Mid extends Root{
static{
//step_2
System.out.println("Mid的静态初始化块");
}
{
//step_6
System.out.println("Mid的普通初始化块");
}
public Mid(){
super();//默认调用父类空参构造器
//step_7
System.out.println("Mid的无参数的构造器");
}
public Mid(String msg){
this();//通过this调用同一类中重载的构造器
//step_8
System.out.println("Mid的带参数构造器,其参数值:" + msg);
}
}
class Leaf extends Mid{
static{
//step_3
System.out.println("Leaf的静态初始化块");
}
{
//step_9
System.out.println("Leaf的普通初始化块");
}
public Leaf(){
super("大虫子,养虫子");//通过super调用父类中有一个字符串参数的构造器
//step_10
System.out.println("Leaf的构造器");
}
}
public class LeafTest{
public static void main(String[] args){
new Leaf();
System.out.println();
new Leaf();
/*
Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:大虫子,养虫子
Leaf的普通初始化块
Leaf的构造器
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:大虫子,养虫子
Leaf的普通初始化块
Leaf的构造器
*/
}
}
class Father {
static {
System.out.println("11111111111");
}
{
System.out.println("22222222222");
}
public Father() {
System.out.println("33333333333");
}
}
public class Son extends Father {
static {
System.out.println("44444444444");
}
{
System.out.println("55555555555");
}
public Son() {
System.out.println("66666666666");
}
//main方法既是程序入口,也是静态方法。由父及子 静态先行。main方法的执行也需要先有类的结构
public static void main(String[] args) {
System.out.println("77777777777");
System.out.println("************************");
new Son();
System.out.println("************************");
new Son();
System.out.println("************************");
new Father();
/*
11111111111
44444444444
77777777777
************************
22222222222
33333333333
55555555555
66666666666
************************
22222222222
33333333333
55555555555
66666666666
************************
22222222222
33333333333
*/
}
}
对属性的显示赋值和在代码块中赋值的先后执行顺序:
public class OrderTest {
public static void main(String[] args) {
Order1 o1 = new Order1();
System.out.println(o1.orderId);//2
Order2 o2 = new Order2();
System.out.println(o2.orderId);//2
}
}
class Order1 {
int orderId = 1;
{
orderId = 2;
}
}
class Order2 {
{
orderId = 1;
}
int orderId = 2;
}