(1.3)--3-2类的生命周期面向对象程序设计.ppt
类的生命周期加载ClassLoader.class链接(验证+准备+解析)初始化使用卸载生成Class类的一个对象初始化类变量为类变量分配空间,赋default值,设置相关数据结构验证格式等处理引用的其它类和接口程序的启动java p1.Test启动虚拟机(加载需要的类)找到p1.Test类的.class文件加载Test(超类、超接口)执行Test的main方法一、类和接口的加载通过ClassLoader和它的子类完成加载根据类的二进制表示形式(如.class),使用ClassLoader的defineClass方法生成Class类的一个对象,代表被加载类 (如p1.Test)Class类虚拟机加载类或接口T后,会为T生成一个Class类的对象,用T.class引用这个对象,或 对象.getClass()引用这个对象。例如:为Point类,生成一个Class类的对象 用Point.class指代这个对象 Point p=new Point();p.getClass();/返回上面的Class的对象通过Class的对象可以获取类Point的相关信息,如有哪些字段、哪些方法。Class对象还用于初始化等比较运算符:instanceoftruetruetruefalsepackage chapter31interface;public class TestInstanceOf public static void main(String args)Person aPerson=new Person(001,Tom);Person aStudent=new Student(002,Mike,Computer);if(aPerson instanceof Person)System.out.println(true);elseSystem.out.println(false);if(aStudent instanceof Person)System.out.println(true);elseSystem.out.println(false);if(aPerson.getClass()=Person.class)System.out.println(true);elseSystem.out.println(false);if(aStudent.getClass()=Person.class)System.out.println(true);elseSystem.out.println(false);isInstancetruetruetruefalsepackage chapter31interface;public class TestIsInstancepublic static void main(String args)Person aPerson=new Person(001,Tom);Person aStudent=new Student(002,Mike,Computer);if(aPerson.getClass().isInstance(aPerson)System.out.println(true);elseSystem.out.println(false);if(aPerson.getClass().isInstance(aStudent)System.out.println(true);elseSystem.out.println(false);if(aStudent.getClass().isInstance(aStudent)System.out.println(true);elseSystem.out.println(false);if(aStudent.getClass().isInstance(aPerson)System.out.println(true);elseSystem.out.println(false);对象所属类判定总结1、o.getClass()=类名.class :o引用的对象所属的类是否同类名2、o instanceof 类名 :o引用的对象能否cast to 类名,能返回真,否则假 3、c.isInstance(o):o引用的对象能否cast to c,能返回真,否则假o:对象c:Class对象,o.getClass()编译时知道o要比较的类,则用o instanceof 类名 编译时不知道o要比较的类,运行时才知道,则用c.isInstance(o)二、链接(link)一个程序由若干个编译单位构成:C语言的.c 文件java语言的.java文件为什么要分成编译单位?一个编译单位会使用其它编译单位的变量、函数只有将所有编译单位合并成一个整体,才能得到一个的 可执行的程序二、链接(link)#include int quadraticEquation(double a,double b,double c,*root1,*root2)double delta=b*b-4.0*a*c;if(delta 0)return 0;root1=(-b+sqrt(delta)/(2.0*a);root2=(-b-sqrt(delta)/(2.0*a);return 1;sqrt是库中的函数库(library):由多个目标文件打包而成C语言的函数调用了类库或其它编译单位的函数等二、链接(link)public class Point.public void printPosition()System.out.println(I am here(+x+,+y+);.public class Rectangle private Point leftCorner;private Point rightCorner;.public class Student extends Person.java的类使用了其它类的方法、字段,引用其它的类或扩展其它类二、链接(link)编译器将编译单位使用的其它编译单位的变量和方法(函数)汇总成一个符号表(symbol table),存放在目标文件(.obj、.class)中链接器根据符号表,找到其它编译单位的变量和方法,合并成一个可执行文件。静态链接:可执行文件中包含所有的数据和代码动态链接:可执行文件中包含部分数据和代码,在用到时 再引入缺失的部分。二、链接(link)java链接步骤:verification:对类或接口的二进制形式进行必要的合规性检查preparation:为类变量分配存储空间,赋予默认值。resolution:解决对其它类和接口的引用 可以一次解决也可以逐步解决 根据类型到对应的类以及超类中查找实实例方法的例方法的resolutionaPerson.print();/调用Person类的print()public void print()StudentPersonpublic void print()Person aPerson.resolution不涉及对象,只是根据引用变量的类型gs.getID();public String getID()StudentPersonGraduateStudent实实例方法的例方法的resolutionGraduateStudent gs.类类方法的方法的resolutionaStudent.getToken();public static String getToken()StudentPersonpublic static String getToken()(Person)aStudent).getToken();public static String getToken()StudentPersonpublic static String getToken()Student aStudent.三、类和接口的初始化何时初始化初始化什么初始化的过程创建对象调用静态方法赋值静态字段引用非constant variable静态字段执行顶层类T中的assert语句调用Class类或java.lang.reflect包中的某些反射函数类和接口初始化的时机类和接口初始化的工作1、按照声明时的先后次序,执行static constant variable变量的初始化语句2、对于类,初始化它的超类和超接口3、按照声明时的先后次序,执行类变量的初始化语句和静态初始化块package chapter31interface;public class ClassVariable private static int s1=100;/4private static final int s2=200;/constant variable 1private static final double s3=s2*Math.PI;/constant variable 2private static final String s4=abc;/constant variable 3private static int s5;private static int s6;/没有初始化,采用默认值static s5=300;/5实例化一个类,将先实例化它的尚未实例化的直接超类以及包含 至少1个default方法的所有超接口。先初始化所依赖的类和接口实例化一个接口,不会引起实例化它的任何直接超接口引用一个字段,只初始化声明它的类或接口,即使引用时使用了 子类名或子接口名作为限定类和接口初始化的过程类:class c extends s implements I1,I2,.,In1.list=2.如果s没有被初始化,list=s.3.按照下面的过程逐一遍历I1,I2,.,In:Ii extends J1,J2,.,Jn 递归遍历Ji,依次将Ji的递归遍历结果IJi以及Ii的中具有 至少1个default方法的超接口并入list list=list IJi1.IJnIi4.递归初始化list中的各成员类和接口初始化的过程类和接口初始化的过程CSI1I2I3I4I5I6I7I8I9如图类和接口的扩展关系,则初始化C之前的初始化列表:list=S,I1,I8,I9,I5,I6,I9,I7,I2,I3递归初始化S:list=I4,I8,I9,I5最终的初始化次序:list=I4,I8,I9,I5,S,I1,I6,I9,I7,I2,I3,C注:对接口层次的遍历是树的后序遍历只有声明了default方法的接口才需要初始化例题-摘自JLS 8class Super static System.out.print(Super);class One static System.out.print(One);class Two extends Super static System.out.print(Two);class Test public static void main(String args)One o=null;Two t=new Two();System.out.println(Object)o=(Object)t);This program produces the output:Super Two false例题-摘自JLS 8class Super static int taxi=1729;class Sub extends Super static System.out.print(Sub);class Test public static void main(String args)System.out.println(Sub.taxi);This program prints only:1729 例题-摘自JLS 8interface I int i=1,ii=Test.out(ii,2);interface J extends I int j=Test.out(j,3),jj=Test.out(jj,4);interface K extends J int k=Test.out(k,5);class Test public static void main(String args)System.out.println(J.i);/引用常量,不引起接口的初始化 System.out.println(K.j);static int out(String s,int i)System.out.println(s+=+i);return i;1 j=3jj=4 3 四、类的使用生成类的实例,即对象对象的生成过程1、为类的各实例字段(超类和自己声明的)分配空间 如果空间不足,抛出OutOfMemory异常2、为各字段赋予默认值(数值类型:0,布尔类型:false,引用类型:null)3、调用对应的构造器 3.1 将实参复制给虚参 3.2 如果第一句是this(.),则按照3.1-3.5执行该构造器,转3.5 3.3 如果第一句是super(.),则执行该构造器 3.4 按照声明的次序执行实例字段的初始化语句和初始化块 3.5 执行构造器的其它语句 如果以上步骤出现错误,将抛出异常4、返回新对象的reference(OID)注意:不会返回null对象的生命周期1、reachable:有live thread将使用的对象2、finalizer-reachable:没有live thread使用,但是从某些finalizable对象 reachable3、unreachable:既没有live thread使用,也没有finalizable对象reachable 1、unfinalized:还没有被自动调用过finalize()方法的对象2、finalizable:还没有被自动调用过finalize()方法,但JVM将最终 会自动的调用该方法的对象。3、finalized:已经被自动调用过finalize()方法的对象 对象的构造器调用了Object的构造器,并成功完成之前,不能成为finalizable对象对象的finalize当对象被回收(reclaimed)前,如果覆盖了finalize()方法,则执行该方法。finalize()方法在Object中声明,被它的子类继承。如果对象存在不能被自动回收机制回收的资源,则需要在该方法中释放。The Java programming language does not specify how soon a finalizer will be invoked,except to say that it will happen before the storage for the object is reused.The Java programming language does not specify which thread will invoke the finalizer for any given object.The Java programming language imposes no ordering on finalize method calls.Finalizers may be called in any order,or even concurrently.五、类的卸载A class or interface may be unloaded if and only if its defining class loader may be reclaimed by the garbage collector.Classes and interfaces loaded by the bootstrap loader may not be unloaded.六、程序结束A program terminates all its activity and exits when one of two things happens:All the threads that are not daemon threads terminate.Some thread invokes the exit method of class Runtime or class System,and the exit operation is not forbidden by the security manager.