代码块:
代码块又称初始化块,属于类中的成员(类中的一部分),类似方法,将逻辑语句封装在方法体中,通过{}包围起来,但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过方法或者类显示调用,而是加载类时,或者创建对象时隐士调用
类的加载(什么时间被加载):
我们在研究代码块,必须先知道类是什么时候被加载的,以下分为3中情况:
1.创建对象实例时候(new)
2.创建子类对象实例,父类也会被加载
3.使用类的静态成员时(包括静态方法和静态属性)
代码块分类:
1.有static修饰的静态代码块
1.当创建对象实例时候(new)时代码块加载:
举例:
package com.test.CodeBlock;
public class Test2 {
public static void main(String[] args) {
SS ss = new SS();
}
}
class SS{
static {
System.out.println("代码块被执行");
}
}
运行结果:
2. 当创建子类对象实例,父类时代码块也会被加载
举例:
package com.test.CodeBlock;
public class Test2 {
public static void main(String[] args) {
SS ss = new SS();
}
}
class SS extends QQ{
static {
System.out.println("SS代码块被执行");
}
}
class QQ{
static {
System.out.println("QQ代码块被加载");
}
}
运行结果:
3.当使用类的静态成员时(包括静态方法和静态属性)代码块被加载:
package com.test.CodeBlock;
public class Test2 {
public static void main(String[] args) {
SS ss = new SS();
System.out.println(ss.name);
ss.test();
}
}
class SS {
public static String name="静态属性";
static {
System.out.println("SS代码块被执行");
}
public static void test(){
System.out.println("静态成员");
}
}
运行结果:
注意:
(1)作用就是对类进行初始化,随着类的加载被执行的,并且只会执行一次
举例:
package com.test.CodeBlock;
public class Test2 {
public static void main(String[] args) {
SS ss = new SS();
SS ss1 = new SS();
}
}
class SS{
static {
System.out.println("代码块被执行");
}
}
运行结果:
总结:可以从代码的运行结果上来看,当多次实例化对象时候,代码块只执行一次
(2)调用顺序
静态代码块和静态属性初始化调用的优先级是一样的,当多个静态代码块和多个静态变量初始化,则按照他们定义的顺序调用
举例:
package com.test.CodeBlock;
public class Test2 {
public static void main(String[] args) {
SS1 ss = new SS1();
System.out.println("============");
SS2 ss2 = new SS2();
}
}
class SS1 {
public static int age=getage();
static {
System.out.println("SS代码块被执行");
}
public static int getage(){
System.out.println("属性值初始化");
return 10;
}
}
class SS2 {
static {
System.out.println("SS代码块被执行");
}
public static int age=getage();
public static int getage(){
System.out.println("属性值初始化");
return 10;
}
}
运行结果:
2.没有static修饰的普通代码块(非修饰代码块)
1.创建对象实例时候(new)
package com.test.CodeBlock;
public class Test3 {
public static void main(String[] args) {
hh hh = new hh();
}
}
class hh{
{
System.out.println("代码块被调用");
}
}
运行结果:
2.创建子类对象实例,父类代码块也会被加载
举例:
package com.test.CodeBlock;
public class Test3 {
public static void main(String[] args) {
nn nn = new nn();
}
}
class hh{
{
System.out.println("父类代码块被调用");
}
}
class nn extends hh{
{
System.out.println("子类代码块被调用");
}
}
运行结果:
注意:
(1).每创建一个对象就会执行一次
举例:
package com.test.CodeBlock;
public class Test2 {
public static void main(String[] args) {
SS ss = new SS();
SS ss1 = new SS();
}
}
class SS{
{
System.out.println("代码块被执行");
}
}
运行结果:
总结:举例中创建了两个对象,可以从运行结果来看,普通代码块执行了两次,因此每创建一个对象就会执行一次
(2)调用顺序
调用普通代码块和普通属性的初始化时,调用的优先级一样的,如果多个代码块和多个普通属性初始化,则按照定义顺序调用
举例:
package com.test.CodeBlock;
public class Test3 {
public static void main(String[] args) {
hh hh = new hh();
System.out.println("============");
kk kk = new kk();
}
}
class hh{
{
System.out.println("代码块被调用");
}
public int age= getage();
public int getage(){
System.out.println("普通属性值初始化");
return 10;
}
}
class kk{
public int age= getage();
public int getage(){
System.out.println("普通属性值初始化");
return 10;
}
{
System.out.println("代码块被调用");
}
}
运行结果:
构造器中隐含super()和调用普通代码块 (重点):
举例:
package com.test.CodeBlock;
public class Test4 {
public static void main(String[] args) {
new uu();
}
}
class tt{
{
System.out.println("父类代码块被调用");
}
public tt() {
// super()
// 调用本类普通代码块
System.out.println("父类构造器被调用");
}
}
class uu extends tt{
{
System.out.println("子类代码块被调用");
}
public uu() {
// super()
// 调用本类普通代码块
System.out.println("子类构造器被调用");
}
}
运行结果:
代码块(静态和非静态)的调用顺序:
静态代码块,静态代码块初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下
1.父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
2.子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
3.父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
4.父类的构造器
5.子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
6.子类的构造器
用法1:
如果类的多个构造器中多次适用重复的语句,可以把重复的语句抽取到代码块中,提高代码的重复利用性
举例:
package com.test.CodeBlock;
public class test1 {
public static void main(String[] args) {
AA aa = new AA("你好");
AA hello = new AA("hello", 1);
}
}
class AA{
private String name;
private int price;
{
System.out.println("我喜欢吃螺蛳粉");
System.out.println("我喜欢吃米饭");
System.out.println("我喜欢吃面条");
}
public AA(String name) {
System.out.println("AA(String name)构造器被调用");
this.name = name;
}
public AA(String name, int price) {
System.out.println("AA(String name, int price)构造器被调用");
this.name = name;
this.price = price;
}
}
运行结果:
总结:当构造器被调用的时,先运行代码块中的内容,然后再运行构造器其他内容