Java中类及方法的加载顺序

1. 虚拟机在首次加载Java类时,会对静态代码块、静态成员变量、静态方法进行一次初始化(静态间按顺序执行)。

2. 只有在调用new方法时才会创建类的实例。

3. 类实例创建过程:父子继承关系,先父类再子类。父类的静态->子类的静态->父类的初始化块->父类的构造方法->子类的初始化块->子类的构造方法

4. 类实例销毁时候:首先销毁子类部分,再销毁父类部分。

例:

package exercise;

public class Main_exer {
	void myMethod(Object o){
		System.out.println("object");
	}
	void myMethod(String s){
		System.out.println("string");
	}
	public static void main(String[] args) {
		Main_exer ma = new Main_exer();
		ma.myMethod(null);
	}
}
输出结果:

string

例:

package classLoader_demo;

public class Parent
{
	//静态成员变量
    public static int t = parentStaticMethod2();
    //代码块
    {
        System.out.println("父类非静态初始化块");
    }
    static
    {
        System.out.println("父类静态初始化块");
    }
    //构造方法
    public Parent()
    {
        System.out.println("父类的构造方法");
    }
    //父类静态方法
    public static int parentStaticMethod()
    {
        System.out.println("父类的静态方法");
        return 10;
    }
    public static int parentStaticMethod2()
    {
        System.out.println("父类的静态方法2");
        return 9;
    }
  
    @Override
    protected void finalize() throws Throwable
    {
        // TODO Auto-generated method stub
        super.finalize();
        System.out.println("销毁父类");
    }
 
}
package classLoader_demo;

public class Child extends Parent
{
	//代码块
    {
        System.out.println("子类非静态初始化块");
    }
    static
    {
        System.out.println("子类静态初始化块");
    }
    //构造方法
    public Child()
    {
        System.out.println("子类的构造方法");
    }
    //静态方法
    public static int childStaticMethod()
    {
        System.out.println("子类的静态方法");
        return 1000;
    }
    
    @Override
    protected void finalize() throws Throwable
    {
        // TODO Auto-generated method stub
        super.finalize();
        System.out.println("销毁子类");
    }
}
当main中语句为
Parent.parentStaticMethod();
输出结果:

父类的静态方法2
父类静态初始化块
父类的静态方法


当main中语句为

Child child = new Child();
		try {
			child.finalize();
		} catch (Throwable e) {
			e.printStackTrace();
		}
输出结果:

父类的静态方法2
父类静态初始化块
子类静态初始化块
父类非静态初始化块
父类的构造方法
子类非静态初始化块
子类的构造方法
销毁父类
销毁子类
此处输出结果中的先输出“销毁父类”,再输出“销毁子类”,与前面提到的先销毁子类再销毁父类并不矛盾。仍然为先调用子类的销毁方法,再调用父类的销毁方法,只是super关键字的原因。

备注:

1. Java中类方法和实例方法的区别

类体中的方法分为实例方法和类方法两种,用static修饰的是类方法。

当类的字节码文件被加载到内存时,类的实例方法不会被分配入口地址,当该类创建对象后,类中的实例方法才分配入口地址,从而实例方法可以被类创建的任何对象调用执行。需要注意的是,当我们创建第一个对象时,类中的实例方法就分配了入口地址,当再创建对象时,不再分配入口地址,也就是说,方法的入口地址被所有的对象共享,当所有的对象都不存在时,方法的入口地址才被取消。

对于类中的类方法,在该类被加载到内存时,就分配了相应的入口地址。从而类方法不仅可以被类创建的任何对象调用执行,也可以直接通过类名调用。类方法的入口地址直到程序退出才被取消。

类方法在类的字节码加载到内存时就分配了入口地址,因此,Java语言允许通过类名直接调用类方法,而实例方法不能通过类名调用。在讲述类的时候我们强调过,在Java语言中,类中的类方法不可以操作实例变量,也不可以调用实例方法,这是因为在类创建对象之前,实例成员变量还没有分配内存,而且实例方法也没有入口地址。


2.  Java程序运行时需加载的几个类

例:

package classLoader_demo;
import java.net.URL;
public class Main_cld {
	public static void main(String[] args) {
		URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();  
        for(int i=0; i < urls.length; i++){  
            System.out.println(urls[i].toExternalForm());  
        }         
        System.out.println("----- 分隔符------");        
        System.out.println(System.getProperty("sun.boot.class.path")); 
	}
}
输出结果:

file:/C:/Program%20Files/Java/jre1.8.0_66/lib/resources.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/rt.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/sunrsasign.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/jsse.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/jce.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/charsets.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/lib/jfr.jar
file:/C:/Program%20Files/Java/jre1.8.0_66/classes
----- 分隔符------
C:\Program Files\Java\jre1.8.0_66\lib\resources.jar;C:\Program Files\Java\jre1.8.0_66\lib\rt.jar;C:\Program Files\Java\jre1.8.0_66\lib\sunrsasign.jar;C:\Program Files\Java\jre1.8.0_66\lib\jsse.jar;C:\Program Files\Java\jre1.8.0_66\lib\jce.jar;C:\Program Files\Java\jre1.8.0_66\lib\charsets.jar;C:\Program Files\Java\jre1.8.0_66\lib\jfr.jar;C:\Program Files\Java\jre1.8.0_66\classes


  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: 在Java通常在程序启动就被加载,而且在运行过程一般不会重新加载。但是,有些情况下可能需要重新加载,比如在开发过程修改了的源代码后需要重新加载以测试修改是否生效。 为了重新加载,可以使用Java的热部署(HotSwap)技术,该技术可以在不停止程序的情况下重新加载已经被加载。在Java,可以通过使用一些工具或框架来实现热部署,比如JRebel和Spring Loaded等。 除了热部署之外,还可以通过使用Java加载器来重新加载Java有多个加载器,可以通过调用加载器的reload方法来重新加载已经被加载。但是,这种方法比较复杂,需要程序员自己实现。因此,在实际开发,一般更倾向于使用热部署技术来重新加载。 ### 回答2: 在Java的重新加载是指在运行动态地改变或重新加载一个已经加载过的Java虚拟机的加载机制规定,每个在内存只能被加载一次,即使重新加载一个,也不会替换掉原来已经加载。 尽管如此,我们可以通过一些技术来实现的重新加载。一种常见的方式是通过自定义加载器实现的重新加载。我们可以自定义一个加载器,在加载之前,检查的更新间。如果的源文件或字节码文件发生了改变,就重新载入这个。 另一种实现的重新加载的方式是使用Java的热部署技术,如JRebel。JRebel工具可以在不重新启动应用程序的情况下,动态地替换的字节码,从而实现的重新加载。 无论使用哪种方式,的重新加载都需要注意以下几点: 1. 确保重新加载与原始具有相同的名和包名,否则会导致运行异常。 2. 在重新加载之前,需要确保原始已经被卸载,否则重新加载不会生效。 3. 对于正在运行的实例,需要注意处理好的版本兼容性,避免出现运行错误。 4. 考虑到性能问题,的重新加载应该谨慎使用,尽量避免频繁地重新加载。 总之,Java重新加载可以通过自定义加载器或使用热部署工具实现。但需要注意一些细节问题,确保重新加载能够正确地被使用。 ### 回答3: 在Java的重新加载是指在程序运行进行更新或替换。Java虚拟机(JVM)默认情况下不支持的重新加载,但可以通过一些特定的技术实现的重新加载。 一种常用的实现重新加载的技术是利用Java加载器机制。Java加载器可以动态加载文件,因此可以通过自定义加载器来实现的重新加载功能。首先,需要编写一个自定义的加载器,该加载器负责从指定的路径或URL加载文件。然后,在程序使用这个自定义的加载加载需要重新加载文件,可以通过修改文件的路径或URL来实现的更新。在客户端代码,可以通过调用自定义加载器的reload方法来重新加载。 另一种实现重新加载的技术是使用热部署框架,例如JRebel。这些框架通过在运行动态地替换的字节码实现的重新加载。通过在IDE安装和配置这些框架,可以在开发过程实现代码的即更新,节省了重新编译和启动的间。 需要注意的是,的重新加载也可能会引发一些问题,例如由于之间的依赖关系导致的加载顺序问题,或者由于状态的改变导致的运行错误。因此,在进行的重新加载,需要谨慎对待,并进行充分的测试和验证。 总而言之,Java可以通过自定义加载器或使用热部署框架来实现的重新加载。这些技术可以加快开发过程的代码更新和调试,提高开发效率。同,在实际应用需注意之间的依赖和测试工作,以确保重新加载能够正确地运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值