Java 类中各成分加载顺序 和 内存中的存放位置

来源:互联网 发布:淘宝代理费 编辑:程序博客网 时间:2024/04/29 19:00

一、什么时候会加载类?
使用到类中的内容时加载:有三种情况
1.创建对象:new StaticCode();
2.使用类中的静态成员:StaticCode.num=9;  StaticCode.show();
3.在命令行中运行:Java StaticCodeDemo

二、类所有内容加载顺序和内存中的存放位置:
利用语句进行分析。
1.Person p=new Person("zhangsan",20);
  该句话所做的事情:
  1).在栈内存中,开辟main函数的空间,建立main函数的变量 p。
  2).加载类文件:因为new要用到Person.class,所以要先从硬盘中找到Person.class类文件,并加载到内存中。
加载类文件时,除了非静态成员变量(对象的特有属性)不会被加载,其它的都会被加载。
记住:加载,是将类文件中的一行行内容存放到了内存当中,并不会执行任何语句。加载时期,即使有输出语句也不会执行。


静态成员变量(类变量)  ----->方法区的静态部分
静态方法                ----->方法区的静态部分
非静态方法(包括构造函数)  ----->方法区的非静态部分
静态代码块----->方法区的静态部分
构造代码块----->方法区的静态部分

注意:在Person.class文件加载时,静态方法和非静态方法都会加载到方法区中,只不过要调用到非静态方法时需要先实例化一个对象,对象才能调用非静态方法。如果让类中所有的非静态方法都随着对象的实例化而建立一次,那么会大量消耗内存资源,所以才会让所有对象共享这些非静态方法,然后用this关键字指向调用非静态方法的对象。

  3).执行类中的静态代码块:如果有的话,对Person.class类进行初始化。
  4).开辟空间:在堆内存中开辟空间,分配内存地址。
  5).默认初始化:在堆内存中建立 对象的特有属性,并进行默认初始化。
  6).显示初始化:对属性进行显示初始化。
  7).构造代码块:执行类中的构造代码块,对对象进行构造代码块初始化。
  8).构造函数初始化:对对象进行对应的构造函数初始化。
  9).将内存地址赋值给栈内存中的变量p。


2.p.setName("lisi");
  1).在栈内存中开辟setName方法的空间,里面有:对象的引用this,临时变量name
  2).将p的值赋值给this,this就指向了堆中调用该方法的对象。
  3).将"lisi" 赋值给临时变量name。
  4).将临时变量的值赋值给this的name。


3.Person.showCountry();
  1).在栈内存中,开辟showCountry()方法的空间,里面有:类名的引用Person。
  2).Person指向方法区中Person类的静态方法区的地址。
  3).调用静态方法区中的country,并输出。
  注意:要想使用类中的成员,必须调用。通过什么调用?有:类名、this、super
  
三、静态代码块、构造代码块和构造函数的区别
静态代码块:用于给类初始化,类加载时就会被加载执行,只加载一次。
构造代码块:用于给对象初始化的。只要建立对象该部分就会被执行,且优先于构造函数。
构造函数:  给对应对象初始化的,建立对象时,选择相应的构造函数初始化对象。
 创建对象时,三者被加载执行顺序:静态代码块--->构造代码块--->构造函数
 //执行顺序:(优先级从高到低。)静态代码块>main方法>构造代码块>构造方法。

1 普通代码块

复制代码
 1 //普通代码块:在方法或语句中出现的{}就称为普通代码块。普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定--“先出现先执行” 2 public class CodeBlock01{ 3       public static void main(String[] args){ 4            5             { 6               int x=3; 7               System.out.println("1,普通代码块内的变量x="+x);     8             } 9             10             int x=1;11             System.out.println("主方法内的变量x="+x);12             13             {14                int y=7;15                System.out.println("2,普通代码块内的变量y="+y);    16             }17           }18     }19     20     /*21     运行结果:22     1,普通代码块内的变量x=323          主方法内的变量x=124          2,普通代码块内的变量y=725     */26     
复制代码

 

2 构造代码块

复制代码
//构造块:直接在类中定义且没有加static关键字的代码块称为{}构造代码块。构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造函数。public class CodeBlock02{    {      System.out.println("第一代码块");        }        public CodeBlock02(){        System.out.println("构造方法");        }                {          System.out.println("第二构造块");        }      public static void main(String[] args){          new CodeBlock02();          new CodeBlock02();          new CodeBlock02();               }}    /**执行结果:第一代码块第二构造块构造方法第一代码块第二构造块构造方法第一代码块第二构造块构造方法*/
复制代码

 

3 静态代码块

复制代码
//静态代码块:在java中使用static关键字声明的代码块。静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。//如果类中包含多个静态代码块,那么将按照"先定义的代码先执行,后定义的代码后执行"。//注意:1 静态代码块不能存在于任何方法体内。2 静态代码块不能直接访问静态实例变量和实例方法,需要通过类的实例对象来访问。class Code{    {      System.out.println("Code的构造块");    }        static{        System.out.println("Code的静态代码块");        }            public Code(){        System.out.println("Code的构造方法");        }    }        public class CodeBlock03{     {      System.out.println("CodeBlock03的构造块");         }          static{        System.out.println("CodeBlock03的静态代码块");        }                public CodeBlock03(){             System.out.println("CodeBlock03的构造方法");            }              public static void main(String[] args){            System.out.println("CodeBlock03的主方法");            new Code();            new Code();            new CodeBlock03();            new CodeBlock03();          }    }/*CodeBlock03的静态代码块CodeBlock03的主方法Code的静态代码块Code的构造块Code的构造方法Code的构造块Code的构造方法CodeBlock03的构造块CodeBlock03的构造方法CodeBlock03的构造块CodeBlock03的构造方法*/
阅读全文
0 0
原创粉丝点击