A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张源锋 中级黑马   /  2013-4-2 21:54  /  1545 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 无奈№追夜 于 2013-4-3 12:12 编辑

  1. public class Test1 {
  2.         public static void main(String[] args) {
  3.                 A a = new A();
  4.                 B b = new B();
  5.                 C c = new C();
  6.                 D d = new D();
  7.         }
  8. }

  9. class A{
  10.         A(){
  11.                 System.out.println("A");
  12.         }
  13. }

  14. class B{
  15.         B(){
  16.                 System.out.println("B");
  17.         }
  18. }

  19. class C{
  20.         C(){
  21.                 System.out.println("c");
  22.         }
  23. }

  24. class D{
  25.         D(){
  26.                 System.out.println("D");
  27.         }
  28. }
复制代码
如上,类加载器是一次性把A B C D全部加载,还是用到哪个类就加载哪个类??如能把你们的测试方法也添上来那就更完美了...

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

4 个回复

倒序浏览
public class Test3 {
        public static void main(String[] args) {
                A a = new A("张三");  //把值传给A的构造函数后就赋值了
                B b = new B();
                C c = new C();
                D d = new D();
                //你建立的是构造函数,构造函数一般用于赋值
                //而你直接在里面使用输出语句,所以创建一次就直接输出了
                //如果你要调用函数可以使用一般函数
                a.show(); //如果注释了就不会被调用
        }
}

class A{
                String name;
        A(String name){
                this.name = name;
        }
        public void show(){
                System.out.println("Aaaa");
        }
}

class B{
        B(){
                System.out.println("B");
        }
}

class C{
        C(){
                System.out.println("c");
        }
}

class D{
        D(){
                System.out.println("D");
        }
}

构造函数是对象的创建一同加载到内存的堆内存中,所以你new对象就直接打印出来了.
回复 使用道具 举报
当程序主动使用某个类的时候,类还没有被加载到内存中。加载的步骤大概如下

1.假如这个类没有被加载和连接,就先加载并连接该类。

2.假如该类的直接父类还没有被初始化,那么先初始化其父类.这里需要明白的是,所有的类的父类是java.lang.Object类(它是类层次结构的根),所以JVM总是会初始化它.依次是下一个父类.以此类推.系统会保证该类的所有父类,包括直接的,间接的,都会被初始化。

3.假如类中有初始化语句块,系统就依次执行这些初始化语句块的语句。
回复 使用道具 举报
麻烦楼主把问题改一下,这是加载顺序问题,不是ClassLoader问题。
回复 使用道具 举报
本帖最后由 刘焕新 于 2013-4-3 02:18 编辑

个人认为,你的示例代码中的类的加载顺序是按照代码的执行顺序加载的,就是用到哪个类才加载哪个类。
Java中的类大致分为三种:
1 系统类;
2 扩展类;
3 程序员自定义的类。
JVM在启动时,只加载一些必须的系统类和扩展类,其余的大多数应用类,将在运行时动态加载。
你可以尝试从JVM的运行效率来分析考虑:假设有非常非常多的类文件等待执行,而如果JVM一次性加载所有的类文件到内存中,将会是什么结果?
JVM的运行效率本来就不是很高,这样做的结果可想而知吧。

JVM需要加载一个.class类文件的时候只有在下面几种情况下才会发生:
1 创建一个java实例对象;
2 调用一个类的静态方法;
3  静态域赋值;
4  访问静态域;
5  在顶层类中执行assert语句
当上面的某个条件发生的时候,ClassLoader才会真正的去加载相应的类。

下面来看看关于类的加载器:
JVM中默认的三个主要的类加载器:
BootStrap:负责加载JRE/librt.jar
ExtClassLoader:负责加载JRE/lib/ext/*.jar
AppClassLoader:负责加载CLASSPATH指定路径下的class文件
当JVM启动的时候,最先运行的是BootStrap加载器,依次往下。
三个类加载器是自上而下的继承关系,从下面代码打印的最后两行可以看出AppClassLoader的父类是ExtClassLoader。
其中,BootStrap不是Java语言编写的类,而是由JVM所在系统的语言编写的。在Windows下,此类就是用C++编写的程序。
  1. class Apple {
  2.         Apple() {
  3.                 System.out.println("Apple");
  4.         }
  5. }

  6. class Boy {
  7.         Boy() {
  8.                 System.out.println("Boy");
  9.         }
  10. }

  11. class Cat {
  12.         Cat() {
  13.                 System.out.println("Cat");
  14.         }
  15. }

  16. class Dog {
  17.         Dog() {
  18.                 System.out.println("Dog");
  19.         }
  20. }

  21. public class Test1 {
  22.         public static void main(String[] args) {
  23.                 Apple a = new Apple();
  24.                 Boy b = new Boy();
  25.                 Cat c = new Cat();
  26.                 Dog d = new Dog();
  27.                
  28.                 System.out.println(a.getClass().getClassLoader());
  29.                 System.out.println(b.getClass().getClassLoader());
  30.                 System.out.println(c.getClass().getClassLoader());
  31.                 System.out.println(d.getClass().getClassLoader());
  32.                
  33.                 ClassLoader loader = a.getClass().getClassLoader();
  34.                 while(loader != null) {
  35.                         //循环打印出ClassLoader的父类
  36.                         System.out.println(loader.getClass().getName());
  37.                         loader = loader.getParent();
  38.                 }
  39.         }
  40. }
复制代码
打印输出结果:
  1. Apple
  2. Boy
  3. Cat
  4. Dog
  5. sun.misc.Launcher$AppClassLoader@19821f
  6. sun.misc.Launcher$AppClassLoader@19821f
  7. sun.misc.Launcher$AppClassLoader@19821f
  8. sun.misc.Launcher$AppClassLoader@19821f
  9. sun.misc.Launcher$AppClassLoader
  10. sun.misc.Launcher$ExtClassLoader
复制代码
从打印输出的结果来看,至少能说明以上4个类对象都是由同一个类加载器加载的,它就是AppClassLoader。

点评

嗯嗯...多谢  发表于 2013-4-3 12:08

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马