Java类的执行顺序

  • 没有继承关系情况的执行顺序 有如下几个成员 : 静态代码块 非静态代码块 无参构造器 有参构造器 main方法(主程序) 静态方法 普通成员方法

  • 按照JVM的内存模型的理想情况的执行顺序: Class字节码被类加载器装载到JVM中,首先Class相关描述信息会放在方法区,然后在堆区创建一个这个类的java.lang.Class对象,用来封装类在方法区类的对象。静态的东西都放在方法区,首次加载Class会初始化静态代码块,静态变量,静态方法,注意,只有首次加载会。然后当我们调用new方法时,实例化该Class的对象,将该对象的指针地址放在栈区,指向堆中的实例。执行无参构造方法,有参构造方法。最后我们调用对象的实例方法,执行普通成员方法。 ##我们new一个对象并调用他的方法,顺序是怎样的呢?

  • 我猜顺序应该是:静态代码块–>mian方法–>非静态代码块–>构造方法–>普通成员方法

不信?上代码


package Oop;

public class Father {
	
	private String name;
	
	static{
		System.out.println("我是静态代码块!");
	}
	
	{
		System.out.println("我是非静态代码块!");
	}
	
	Father(){
		System.out.println("我是无参构造方法!");
	}
	
	Father(String name){
		this.name = name;
		System.out.println("name:"+name+"我是有参构造方法!");
	}
	
	public static int classStaticMethod(){
		System.out.println("我是静态方法!");
		return 10;
	}
	
	public void say(String name){
		System.out.println("我是普通成员方法:"+name);
	}
	
	public static void main(String[] args) {
		System.out.println("我是main方法!");
		Father f = new Father("panda");
		f.say("hello!"+f.name);
		//Father.classStaticMethod();
		
	}
	
}
  • 结果是
我是静态代码块!
我是main方法!
我是非静态代码块!
name:panda我是有参构造方法!
我是普通成员方法:hello!panda
  • 接下来我们把
Father f = new Father("panda");
        f.say("hello!"+f.name);

这2句注释,把 //Father.classStaticMethod(); 这句取消注释,结果又是如何呢?

  • 结果是
我是静态代码块!
我是main方法!
我是静态方法!

Tip:静态方法只有我们去手动调才会执行,构造方法调用的就是我们new对象的时候,传的参数和调用的一致(无参的就调用无参构造方法)

####接下来玩点难的 嘻嘻

  • 有继承关系的执行顺序 有如下成员: 父类静态代码块 父类非静态代码块 父类无参构造器 父类有参构造器 父类静态方法 父类普通成员方法 子类静态代码块 子类非静态代码块 子类无参构造器 子类有参构造器 子类重写父类普通方法 子类main方法(主程序) 子类静态方法 子类普通成员方法

####顺序又是怎样的呢?上代码 我们先把Father类改了一下,好区分点

package Oop;

public class Father {
	
	private String name;
	
	static{
		System.out.println("我是父类的静态代码块!");
	}
	
	{
		System.out.println("我是父类的非静态代码块!");
	}
	
	Father(){
		System.out.println("我是父类的无参构造方法!");
	}
	
	Father(String name){
		this.name = name;
		System.out.println("name:"+name+"我是父类的有参构造方法!");
	}
	
	public static int classStaticMethod(){
		System.out.println("我是父类的静态方法!");
		return 10;
	}
	
	public void say(String name){
		System.out.println("我是父类的普通成员方法:"+name);
	}
	
	public static void main(String[] args) {
		System.out.println("我是父类的main方法!");
		//Father f = new Father("panda");
		//f.say("hello!"+f.name);
		Father.classStaticMethod();
		
	}
}
package Oop;

public class Son extends Father {
	private String name;
	
	static{
		System.out.println("我是子类的静态代码块!");
	}
	
	{
		System.out.println("我是子类的非静态代码块!");
	}
	
	Son(){
		//super();
		System.out.println("我是子类的无参构造方法!");
	}
	
	Son(String name){
		super("panda1");
		this.name = name;
		System.out.println("我是子类的有参构造方法!"+name);
	}
	public static int sonStaticMethod(){
		System.out.println("我是子类的静态方法");
		return 11;
	}
	
	@Override
	public void say(String name){
		System.out.println("我是子类重写父类的普通方法!");
	}
	
	public void eat(){
		System.out.println("我是子类的普通方法");
	}
	
	public static void main(String[] args) {
		System.out.println("我是子类的main方法");
		Father f = new Son("ddd");
		f.say("say...");
	}
}

聪明的你知道答案了么。。。

  • 结果
我是父类的静态代码块!
我是子类的静态代码块!
我是子类的main方法
我是父类的非静态代码块!
name:panda1我是父类的有参构造方法!
我是子类的非静态代码块!
我是子类的有参构造方法!ddd
我是子类重写父类的普通方法!

以上2中情况都是说的对象创建的情况,那么当对象没有引用指向他时,销毁的顺序是什么样的呢?

我们在Father类和Son类分别重写finalize()方法,如下

@Override
	protected void finalize() throws Throwable{
		super.finalize();
        System.out.println("销毁父类");
	}
@Override
	protected void finalize() throws Throwable{
		super.finalize();
        System.out.println("销毁子类");
	}

重写运行Son类main方法,好吧,,其实这个销毁方法不会被调用。。。。有大神告诉我这是为啥吗。。但是,结论我知道: 先销毁子类实例,再销毁父类实例 具体原理不知道。。。

总结:

  • 没有继承关系时,类的初始化顺序是:先静态代码块后非静态代码块后静态方法后构造方法后普通实例方法
  • 有继承关系是,类的初始化顺序是:先父静后子静后父构造后子构造后子普通实例方法

给TA打赏
共{{data.count}}人
人已打赏
技术教程投稿

javaSE遍历HashMap的5种最佳方式

2023-3-17 19:11:48

技术教程投稿

IDEA 性能优化设置

2023-3-18 10:12:14

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索