一、对象的初始化 (疯狂java160)
1、父类静态初始化块 子类初始化块 (静态只执行一次,仅在第一次初始化对象时调用,第二次不再调用)
2、父类普通初始化块 父类无参构造函数 父类有参构造函数
3、子类普通初始化块 子类构造函数
二、 类的加载 是由类加载器完成的,类加载器包括:根加载器( BootStrap )、扩展加载器( Extension )、系统加载器( System )和用户自定义类加载器( java.lang.ClassLoader 的子类)。一个类被加载后,同一个类(同包,同类名,同加载器)不会再被加载。
从 Java 2 ( JDK 1.2 )开始,类加载过程采取了父亲委托机制(PDM )。 PDM 更好的保证了 Java 平台的安全性,在该机制中, JVM 自带的 Bootstrap 是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。 JVM 不会向 Java 程序提供对 Bootstrap 的引用。下面是关于几个类加载器的说明:
- 引导类加载器(bootstrap class loader):是用原生代码来实现的,它用来加载 Java 的核心库( rt.jar );
- 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。从 java.ext.dirs 系统属性所指定的目录中加载类库,又叫应用类加载器,其父类是 Extension 。它是应用最广泛的类加载器。它从环境变量 classpath或者系统属性 java.class.path 所指定的目录中记载类,它的父加载器是 Bootstrap ;
- 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类
- 用户自定义类加载器: java.lang.ClassLoader 的子类
- tomcat 为每个 App 创建一个 Loader,里面保存着此 WebApp 的 ClassLoader。需要加载 WebApp 下的类时,就取出 ClassLoader 来使用
父类委托机制是可以修改的,有些服务器就是自定义类加载器优先的。
三、反射查找
1、程序运行时发现对象和类的真实信息 方法
- 假设在编译时和运行时都完全知道类型的具体信息,先使用instanceof运算符进行判断,再利用强制类型转换将其转换成其运行时类型的变量。 Person p= new Student(); 编译类型为Person 运行时类型为 Student
- 编译时无法预知该对象和类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息,这就需要用到反射。
3、从Class中获取信息:Class类提供了大量实例方法获取Class类对应的详细信息。可以获取其对应类的构造器,方法,包含的成员变量,Annotation(注释),内部类, 外部类。。。。。。
- 使用Class类的forName(String clazzName)静态方法,参数为类的全限定类名。如:Class<? > jframeClass= Class.forname("javax.swing.JFrame"); Object obj =ctor.newInstance("测试窗口")。
- 调用类的class属性获取该对象的Class对象。如Person.class将会返回Person类对应的Class对象。
- 调用某个对象的getClass()方法。其为java.lang.Object类的一个方法。返回该对象对应的Class对象。
4、使用反射生成并操作对象
- 创建对象。(1).Class对性的newInstance()方法创建该Class对象对应类的实例。(2).使用Class对象获取构造器Constructor对象,调用Constructor对象的newInstance()方法穿件对应类实例
- 调用方法。获取Class对象后可以通过调用Class对象的getMethods()方法或者getMethod()方法来获取全部方法或者指定方法。
- 访问成员变量值。通过Class浮想的getFieilds()或者getField()方法可以获取该类所包括的全部成员变量。
- getXxx(Object obj):获取obj对象的该成员变量的值。此处Xxx对应8种基本类型。如果为引用类型,取消get后边的Xxx。
- setXxx(Object obj,Xxx val):将obj对象的该成员变量值 设置成 val值。此处Xxx对应8种基本类型。引用类型,去掉Xxx。