代码块又称初始化块,属于类中的成员,类似于方法将逻辑封装在方法体中(只有方法体的方法)。
使用场景:多个构造器中都有重复的语句可以抽取到代码块中提高代码的复用性。
使用格式(有static修饰则为静态代码块,没有static修饰则为普通代码块):
[修饰符(static)]{
方法体;
}
使用注意点:
1.static代码块作用是对类进行初始化,随着类的加载而执行,且只会执行一次;
普通代码块随着对象的创建而执行,每创建一次就执行一次。
2.类的加载
(1)创建对象实例时
package CodeBlockDetail;
public class CodeBlockDetail02 {
public static void main(String[] args) {
new student();
}
}
class student{
static{
System.out.println("代码块被调用");
}
}
(2)创建子类对象实例时,父类也会被加载,而且父类先被加载,子类后被加载
package CodeBlockDetail;
public class CodeBlockDetail03 {
public static void main(String[] args) {
new children();
}
}
class parents{
static{
System.out.println("父类静态代码块被调用");
}
}
class children extends parents{
static{
System.out.println("子类静态代码块被调用");
}
}
输出结果为
(3)使用类的静态成员时
package CodeBlockDetail;
public class CodeBlockDetail01 {
public static void main(String[] args) {
Person.mean();
System.out.println(Person.age);
}
}
class Person{
static int age=10;
static{
System.out.println("代码块被调用");
}
public static void mean(){
System.out.println("静态方法");
}
}
输出结果为(代码块只会调用一次,但静态方法和静态属性调用后,类都会加载)
3.普通代码块,在创建对象实例时会被隐式的调用,被创建一次就调用一次;
如果只是使用类的静态成员时,普通代码块并不会被执行。
package CodeBlockDetail;
public class CodeBlockDetail05 {
public static void main(String[] args) {
People people01 = new People();
People people02 = new People();
People people03 = new People();
System.out.println(People.age);
}
}
class People{
public static int age=20;
{
System.out.println("普通代码块被调用");
}
}
输出结果为(创建三次对象调用三次普通代码块,静态属性调用后,普通代码块不会执行)
4.在创建一个对象时,在一个类中的调用顺序是:
(1)调用静态代码块和静态属性初始化(二者优先级相同,按照定义顺序调用)
(2)调用普通代码块和普通属性初始化(二者优先级相同,按照定义顺序调用)
(3)调用构造器
package CodeBlockDetail;
public class CodeBlockDetail06 {
public static void main(String[] args) {
Person person = new Person();
}
}
class Person{
//(1)静态属性初始化
public static int age=initial();
//(3)普通属性初始化
public int age1=initial1();
//(2)静态代码块
static{
System.out.println("静态代码块被调用");
}
//(4)普通代码块
{
System.out.println("普通代码块被调用");
}
//(5)无参构造器
public Person(){
System.out.println("无参构造器被调用");
}
public static int initial(){
System.out.println("initial被调用");
return 20;
}
public static int initial1(){
System.out.println("initial1被调用");
return 80;
}
}
输出结果为
5.构造器最前面其实隐含了super()和调用普通代码块(静态相关的代码块,属性初始化,在类加载时就执行完毕,因此是优于构造器和普通代码块执行的)
package CodeBlockDetail;
public class CodeBlockDetail03 {
public static void main(String[] args) {
new children();
}
}
class parents{
public parents() {
//super();
//调用本类普通代码块
System.out.println("父类构造器被调用");
}
}
class children extends parents{
public children() {
System.out.println("子类构造器被调用");
}
{
System.out.println("子类普通代码块被调用");
}
}
输出结果为
6.创建一个子类时,他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序:
(1)父类的静态代码块和静态属性初始化(二者优先级相同,按照定义顺序调用)
(2)子类的静态代码块和静态属性初始化(二者优先级相同,按照定义顺序调用)
(3)父类的普通代码块和普通属性初始化(二者优先级相同,按照定义顺序调用)
(4)父类的构造方法
(5)子类的普通代码块和普通属性初始化(二者优先级相同,按照定义顺序调用)
(6)子类的构造方法
package CodeBlockDetail;
import Static.StaticMethod;
import java.util.stream.StreamSupport;
public class CodeBlockDetail04 {
public static void main(String[] args) {
//进行类的加载 1。加载父类 2.加载子类
//创建对象
new kids();
}
}
class parent{
public String name=means1();
private static int age=a();
static{
System.out.println("父类静态代码块被调用");
}
{
System.out.println("父类普通代码块被调用");
}
public static int a(){
System.out.println("父类静态属性初始化被调用");
return 40;
}
public parent(){
System.out.println("父类构造器");
}
public String means1(){
System.out.println("父类普通属性初始化被调用");
return "父";
}
}
class kids extends parent{
public String name=means2();
private static int age=b();
static{
System.out.println("子类的静态代码块被调用");
}
{
System.out.println("子类普通代码块被调用");
}
public static int b(){
System.out.println("子类静态属性初始化被调用");
return 18;
}
public kids() {
//隐藏了super();
//普通代码块
System.out.println("子类构造器");
}
public String means2(){
System.out.println("子类普通属性初始化被调用");
return "子类";
}
}
输出结果为
7.静态代码块只能调用静态成员,普通代码块能调用任意成员。