面向对象--代码块--代码块的执行顺序
代码块的执行顺序
讲解代码块的目的:今后面试的时候,会有相关程序题,需要熟悉不同的代码块的执行顺序
代码块:
在Java中,使用{}括起来的代码被称为代码块
根据其位置和声明的不同,可以分为
-
局部代码块(当作正常的代码看待)
格式:只在方法中出现,使用大括号括起来的代码叫局部代码块
优点:使用完毕及早释放,提高内存的使用率
执行顺序:在一个方法中,自上而下的顺序执行
-
构造代码块
位置:在类中方法外定义,
执行顺序:每次调用构造方法的时候,都会先执行一遍构造代码块再执行构造方法 构造代码块 >--> 构造方法
如果在main方法中new对象的时候,也有局部代码块,执行顺序自上而下
-
静态代码块
格式:被static修饰的代码块,定义在类中方法外
执行顺序:静态代码块 -- 构造代码块 -- 构造方法
static代码块一旦被执行过一次后,同一个程序不会重复执行。
静态的内容是属于类的本身,程序的开始到结束只会加载一次,不会重复加载
-
同步代码块(多线程讲解)
程序示例
/*
局部代码块
*/
public class CodeDemo {
public static void main(String[] args) {
// 局部代码块格式
{
int a = 100;
System.out.println(a);
}
// 局部代码块运行完毕时候及早释放,所以外部读取不到变量a
// System.out.println(a);
int a2 = 11;
System.out.println(a2);
{
int b = 200;
System.out.println(b);
}
//运行顺序是a>-->a2>-->b 自上而下的顺序执行
}
}
/*
构造代码块
*/
class Demo {
//无参构造方法
Demo() {
System.out.println("Demo无参构造方法");
}
//构造代码块
{
int x = 200;
System.out.println(x);
}
}
public class CodeDemo {
public static void main(String[] args) {
//执行顺序先构造代码块>-->再构造方法
Demo demo = new Demo();
//又new了一次,执行顺序先构造代码块>-->再构造方法
Demo demo1 = new Demo();
//所以每new依次都会先执行一遍构造代码块再执行一遍构造方法
}
}
/*
构造代码块与局部代码块
*/
public class CodeDemo {
// 构造方法
CodeDemo() {
int y = 400;
System.out.println(y);
}
// 构造代码块
{
int q = 500;
System.out.println(q);
}
public static void main(String[] args) {
// 局部代码块
{
int a = 100;
System.out.println(a);
}
// 局部变量
int a2 = 11;
System.out.println(a2);
{
int b = 200;
System.out.println(b);
}
Demo d = new Demo();
//执行顺序?
// 先加载main()方法
// 然后程序自上而下 a>-->a2>-->b
// 然后加载构造方法创建对象
// 但是构造代码块在构造方法前面执行,所以 a>-->a2>-->b>-->q>-->y
// 如果创建对象的步骤放在 局部代码块a前面 q>-->y>-->a>-->a2>-->b
// 如果创建对象的步骤放在 局部代码块a、a2之间 a>-->q>-->y>-->a2>-->b
// 是按照代码前后顺序来的
}
}
//静态代码块
class Demo {
//无参构造方法
Demo() {
System.out.println("Demo无参构造方法");
}
//构造代码块
{
int x = 200;
System.out.println(x);
}
//静态代码块
static {
int w = 99;
System.out.println(w);
}
}
public class CodeDemo {
public static void main(String[] args) {
{
int a = 100;
System.out.println(a);
}
int a2 = 11;
System.out.println(a2);
{
int b = 200;
System.out.println(b);
}
Demo d = new Demo();
/*
执行顺序:JVM先加载main()方法然后程序自上而下执行a➡a2➡b
然后再执行 Demo d = new Demo();w➡x➡Demo无参构造方法
因为static修饰的代码块为静态代码块,随着类的加载而加载
所以要创建Demo类的对象d的时候静态代码块在构造代码块和构造方法之前被加载。
*/
}
}
//局部代码块、构造代码块、静态代码块
class Demo {
//无参构造方法
Demo() {
System.out.println("Demo无参构造方法");
}
//构造代码块
{
int x = 200;
System.out.println(x);
}
//静态代码块
static {
int w = 99;
System.out.println(w);
}
}
public class CodeDemo {
CodeDemo() {
int y = 400;
System.out.println(y);
}
{
int q = 500;
System.out.println(q);
}
static {
int r = 700;
System.out.println(r);
}
public static void main(String[] args) {
{
int a = 100;
System.out.println(a);
}
int a2 = 11;
System.out.println(a2);
{
int b = 200;
System.out.println(b);
}
Demo d = new Demo();
CodeDemo codeDemo = new CodeDemo();
/*
此时执行顺序为?
首先运行程序,JVM会将class文件和静态成员加载到方法区中,
静态区中两个class文件的静态成员在里面的位置其实是分开的,
之后java虚拟机会去CodeDemo的静态区中识别CodeDemo的main方法()
而在CodeDemo的静态区里还有静态代码块,
所以JVM会先执行CodeDemo的静态代码块再把main方法加载到栈里面。
所以先执行静态代码块r,然后JVM将main方法加载到栈中,
之后执行main方法里面的 a➡a2➡b(上面有这里不做解释),
然后调用无参构造方法为Demo创建对象d,执行w➡x➡Demo无参构造方法。
之后调用无参构造方法为CodeDemo创建对象codeDemo,执行q➡y。
(为什么没有r?因为静态代码块在被执行过一次之后,再次调用不执行。)
*/
}
}