面向对象编程(高级部分)——代码块

目录

1. 基本介绍

2. 基本语法

3. 代码块的好处和案例演示

4. 代码块使用注意事项和细节讨论

5. 代码块练习题


1. 基本介绍

2. 基本语法

3. 代码块的好处和案例演示

我们创建一个类

class Movie{
	private String name;
	private double price;
	private String director;
	public Movie(String name) {
		System.out.println("电影屏幕打开...");
		System.out.println("广告开始...");
		System.out.println("电影正式开始...");
		this.name = name;
	}
	public Movie(String name, double price) {
		System.out.println("电影屏幕打开...");
		System.out.println("广告开始...");
		System.out.println("电影正式开始...");
		this.name = name;
		this.price = price;
	}
	public Movie(String name, double price, String director) {
		System.out.println("电影屏幕打开...");
		System.out.println("广告开始...");
		System.out.println("电影正式开始...");
		this.name = name;
		this.price = price;
		this.director = director;
	}
	
	
}

此时这个类里面的3个构造器构成了重载,我们在3个构造器里都要输出3个内容:电影屏幕打开,广告开始,电影正式开始。

这样的话代码就比较冗余了,每个构造器都有这三句话,这时我们可以把相同的语句放入到一个代码块中即可

public class CodeBlock01 {
	public static void main(String[] args) {
		Movie movie = new Movie("你好,李焕英");
	}
}
class Movie {
	private String name;
	private double price;
	private String director;
	{
		System.out.println("电影屏幕打开...");
		System.out.println("广告开始...");
		System.out.println("电影正式开始...");
	}
	public Movie(String name) {
		System.out.println("Movie(String name) 构造器 被调用");
		this.name = name;
	}
	public Movie(String name, double price) {
		this.name = name;
		this.price = price;
	}
	public Movie(String name, double price, String director) {
		this.name = name;
		this.price = price;
		this.director = director;
	}
}

这样的话,不管当我们调用哪个构造器创建对象,都会调用代码块的内容。

此时我们执行一下:

也就是说,代码块调用的顺序是优先于构造器的。


4. 代码块使用注意事项和细节讨论

(2) 类什么时候被加载

1. 创建对象实例时

public class CodeBlockDetail01 {
	public static void main(String[] args) {
		
		
		//类加载情况举例
		//1.创建对象实例(new)
		AA aa = new AA();

	}
}
class AA {
	//静态代码块
	static{
		System.out.println("AA 的静态代码块1被执行..");
	}
}

此时我们new一个AA创建对象实例,然后我们去运行

这时候,AA的静态代码块被执行

2. 创建子类对象实例,父类也会被加载

public class CodeBlockDetail01 {
	public static void main(String[] args) {
		//类加载情况举例
		//2.创建子类对象实例,父类也会被加载
		AA aa = new AA();
	}
}

class AA extends BB{
	//静态代码块
	static{
		System.out.println("AA 的静态代码块1被执行..");
	}
}

class BB{
	static{
		System.out.println("BB 的静态代码块1被执行..");
	}
}

此时创建子类对象实例,父类也会被加载,而且父类先被加载,子类后被加载

3. 使用类的静态成员时(静态属性、静态方法)

public class CodeBlockDetail01 {
	public static void main(String[] args) {
		System.out.println(Cat.n1);
	}
}

class Cat{
	
	public static int n1 = 999; //静态属性
	
	static{
		System.out.println("Cat 的静态代码块1被执行..");
	}
}

此时我们在Cat类里面写一个静态属性,还写一个静态代码块,我们在main方法里去使用静态属性,也会导致静态代码块执行,并且是先执行静态代码块。


public class CodeBlockDetail01 {
	public static void main(String[] args) {
		//类加载情况举例
		//1.创建对象实例(new)
		//AA aa = new AA();
		//2.创建子类对象实例,父类也会被加载
		//AA aa = new AA();
		//System.out.println(Cat.n1);
		DD dd = new DD();
		DD dd1 = new DD();
	}
}

class DD{
	static{
		System.out.println("DD 的静态代码1被执行...");
	}
	
	{
		System.out.println("DD 的普通代码块...");	
	}
}


public class CodeBlockDetail01 {
	public static void main(String[] args) {
		System.out.println(DD.n1);
	}
}

class DD{
	public static int n1 = 88888; //静态属性
	
	static{
		System.out.println("DD 的静态代码1被执行...");
	}
	
	{
		System.out.println("DD 的普通代码块...");	
	}
}

可以这样理解,普通代码块是构造器的补充,构造器被调用了,那么普通代码块也会被调用。构造器没被调用,普通代码块也不会被调用


public class CodeBlockDetail02 {

	public static void main(String[] args) {
		A a = new A();
	}
	
}

class A{
	
	//静态属性的初始化
	private static int n1 = getN1();
	
	static{ //静态代码块
		System.out.println("A 静态代码块...");
	}
	
	public static int getN1(){
		System.out.println("getN1被调用...");
		return 100;
	}
}

那么此时我们将静态代码块放在最前面,输出顺序就变了

public class CodeBlockDetail02 {

	public static void main(String[] args) {
		A a = new A();
	}
	
}

class A{

	static{ //静态代码块
		System.out.println("A 静态代码块...");
	}
	
	//静态属性的初始化
	private static int n1 = getN1();
	
	public static int getN1(){
		System.out.println("getN1被调用...");
		return 100;
	}
}


public class CodeBlockDetail02 {

	public static void main(String[] args) {
		A a = new A();
	}
	
}

class A{
	
	private int n2 = getN2();//普通属性的初始化
	
	{ //普通代码块
		System.out.println("A 普通代码块01");
	}

	static{ //静态代码块
		System.out.println("A 静态代码块01");
	}
	
	//静态属性的初始化
	private static int n1 = getN1();
	
	public static int getN1(){
		System.out.println("getN1被调用...");
		return 100;
	}

	private int getN2() { //普通方法/非静态
		System.out.println("getN2被调用...");
		return 200;
	}
}

前面的静态属性和静态代码块肯定是没变的,那在输出完静态后,肯定是普通代码块了,普通代码块和普通属性的初始化也是按定义的顺序进行调用


最后调用的才是构造器

public class CodeBlockDetail02 {
	public static void main(String[] args) {
		A a = new A();
	}
	
}
class A{
	
	private int n2 = getN2();//普通属性的初始化
	
	{ //普通代码块
		System.out.println("A 普通代码块01");
	}
	static{ //静态代码块
		System.out.println("A 静态代码块01");
	}
	
	//静态属性的初始化
	private static int n1 = getN1();
	
	public static int getN1(){
		System.out.println("getN1被调用...");
		return 100;
	}
	private int getN2() { //普通方法/非静态
		System.out.println("getN2被调用...");
		return 200;
	}
	
	public A(){
		System.out.println("A() 构造器被调用");
	}
}


结论:  

public class CodeBlockDetail03 {
	public static void main(String[] args) {
		new BBB();
	}
	
}
class AAA{
	
	public AAA() {
		//(1)super()
		//(2)调用本类的普通代码块
		System.out.println("AAA() 构造器被调用....");
	}
}
class BBB extends AAA{
	
	{
		System.out.println("BBB的普通代码块...");
	}
	
	public BBB() {
		//(1)super()
		//(2)调用本类的普通代码块
		System.out.println("BBB() 构造器被调用");
	}
	
}

如果在AAA类里面加一个普通代码块,那就是在输出AAA的构造器之前,先输出父类的普通代码块


public class CodeBlockDetail04 {
	public static void main(String[] args) {
		new B02();
	}
}

class A02 { //父类

	private static int n1 = getVal01();

	static {
		System.out.println("A02的一个静态代码块...");
	}

	{
		System.out.println("A02的一个普通代码块...");
	}

	public int n3 = getVal02();

	public static int getVal01() {
		System.out.println("getVal01");
		return 10;
	}

	public int getVal02() {
		System.out.println("getVal02");
		return 10;
	}

	public A02() {
		System.out.println("A02的构造器");
	}
}

class B02 extends A02 {

	private static int n3 = getVal03();

	static {
		System.out.println("B02 的一个静态代码块..");
	}

	public int n5 = getVal04();

	{
		System.out.println("B02 的第一个普通代码块..");

	}

	public static int getVal03() {
		System.out.println("getVal03");
		return 10;
	}

	public int getVal04() {
		System.out.println("getVal04");
		return 10;
	}

	public B02() {//构造器
		System.out.println("B02 的构造器");
	}

}

 首先是类加载:
1.先是父类的静态代码块和静态属性
  getVal01
2.A02的一个静态代码块...
3.然后是子类的静态代码块和静态属性
  getVal03
4.B02 的一个静态代码块..
5.这时候类加载好了,我们在main方法里new了一个子类B02;由于子类构造方法里super()和普通方法块,那么先去父类那里
  A02的一个普通代码块...
6.getVal02
7.最后要记得执行父类的构造器,不然回不去子类.
  A02的构造器
8.那么现在回到子类的构造器继续执行子类的普通代码块
  getVal04
9.B02 的第一个普通代码块..
10.B02 的构造器 

这是一个相对完整的一个对象构建顺序


  

class C02{
	private int n1=100;
	private static int n2 = 200;
	
	private void m1(){}
	
	private static void m2(){}
	
	static{
		//静态代码块只能调用静态成员
//		System.out.println(n1); 错误
		System.out.println(n2); //ok
//		m1(); 错误
		m2();//ok
 	}
 	
	{
		//普通代码块,可以使用任意成员
		System.out.println(n1);
		System.out.println(n2);
		m1();
		m2();
	}
}

5. 代码块练习题

输出结果:  

in static block!
total = 100
total = 100 

因为Person.total会让类加载,此时先去输出静态代码块的内容,然后再输出total的值 。


输出内容:

静态成员sam初始化
static块执行
sam1成员初始化
Test默认构造函数被调用 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GodAiro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值