什么是代码块?
代码块既是用{ }括起来的一段代码。
代码块的分类
根据代码块的所出现的位置以及修饰它的关键字,可以将将代码块可分为以下四种:
1.局部代码块
概念:定义在方法中,用{ }括起来的一段代码。主要用来解决在方法中同名变量的定义问题。本质上是作用域和生命周期的问题。
public class Test
{
public static void main(String[] args)
{
{
int num = 10;
System.out.println("num="+num);
}
int num = 20;
System.out.println("num="+num);
}
}
第一个num的作用域为大括号里面,程序运行时一旦出了大括号,则括号中的num出栈就不复存在了。第二个num的的作用域为定义它之后的整个主方法,在主方法中在它定以后的任何地方都能使用它(不能在它定义前使用它)。
2.构造块
概念: 定义在类中的一段代码块(不加任何修饰符)。可以用来做一些属性的初始化工作。构造块中可以调用方法。
class Student
{
private String name;
// 构造块
{
System.out.println("Studnet类的构造块");
}
//构造方法
public Student()
{
System.out.println("Studnet类的构造方法");
}
}
public class Test
{
public static void main(String[] args)
{
Student stu1 = new Student ();
Student stu2 = new Student ();
}
}
结论:可以看出构造块优先于构造方法执行,每产生一个对象则调用一次构造块和构造方法。没有对象的产生,就没有构造块和构造方法的执行,也就是说构造块和构造方法是和对象密切相关的!在构造块中也可以对属性进行初始化。
3.静态代码块
概念: 静态代码块是用static 关键字修饰,定义在类中的构造块。
分类: 1.在主类中的静态块------静态块的位置在主类中。
public class Test
{
public static void main(String[] args)
{
System.out.println("2.主方法执行");
}
static
{
System.out.println("1.主类中的静态块");
}
}
结论:可以看出主类中的静态块优先于主方法执行。即使静态代码块的位置在主方法的后面.。
原因:JVM虚拟机运行程序时首先找主方法(主方法是程序的入口),而主方法在主类中,因此先找到主类,静态块的执行与对象无关,只要有类加载,就必然要执行静态代码块。
注:不能把静态代码块定在在主方法里面。
2.在非主类中的静态代码块。
class Student
{
public static String name;
static
{
System.out.println("Studnet类的静态代码块");
}
{
System.out.println("Studnet类的构造块块");
}
public Student()
{
System.out.println("Studnet类的构造方法");
}
}
public class Test
{
public static void main(String[] args)
{
System.out.println("主方法执行");
Student.name = "张三";
}
}
输出结果:
结论:主方法优先于非主类中的静态块执行。而且静态代码块的执行与对象没有关系,没有创建任何对象,因此没有构造块和构造方法的执行。之所以静态块能执行,是因为 Student.name = “张三”;该语句访问了Student中的静态成员变量,也就是有类加载这个过程,因此静态块的执行时间由该类的加载时间而定,不论定义多少个对象,类的静态块只执行一次。静态块的作用主要是对静态属性进行初始化及对静态方法的调用。
与继承相关联的代码块的执行顺序(阿里笔试题)
class Person
{
private String name;
private int age;
static
{
System.out.println("1.Person类的静态块");
}
{
System.out.println("2.Person类的构造快");
}
Person()
{
System.out.println("3.Person类的构造方法");
}
}
class Worker extends Person
{
private float salary;
static
{
System.out.println("4.Worker类的静态块");
}
{
System.out.println("5.Worker类的构造快");
}
Worker()
{
System.out.println("6.Worker类的构造方法");
}
}
public class Test
{
public static void main(String[] args)
{
System.out.println("7.主方法开始执行");
Worker work1 = new Worker();
Worker work2 = new Worker();
System.out.println("8.主方法执行完毕");
}
static
{
System.out.println("9.主类的静态块");
}
}
输出结果:
分析一下:JVM虚拟机开始执行该程序,首先找主方法,因为主方法在主类中,因此必须先加载主类,主类中的静态块此时就会被执行(9),因为此时还没有用到Person,Worker类,即这两个类还没有被加载,所以它们的静态代码块不执行。然后进入主方法则显示主方法开始执行(7),在主方法中创建Worker类的对象,创建该类的对象则必然要加载该类,又因为该类继承了Person类,所以首先加载Person类,加载类的同时执行类中的静态代码块(1,4)。
因为创建了对象必然要执行构造块和调用构造方法,(在实例化子类对象前必须先实例化父类对象)因为Worker类是Person类的子类,因此首先执行Person类的构造块和调用Person类构造方法(2,3)然后再执行子类即Worker类的构造块和构造方法(5,6),因为创建了两个对象而静态块的执行仅与类加载有关,因此它只执行一次,(此时不执行1,4)接着创建第二个Worker类对象继续执行(2,3,5,6),此时两个对象已经创建完毕,执行8,所以总的执行顺序为9 7 1 4 2 3 5 6 2 3 5 6 8!