类的加载
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
加载
就是指将class文件读入内存,并为之创建一个Class对象。
任何类被使用时系统都会建立一个Class对象。
连接
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用
初始化 就是我们以前讲过的初始化步骤
类加载器
负责将.class文件加载到内在中,并为之生成对应的Class对象。
虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。
类加载器的组成
Bootstrap ClassLoader 根类加载器
Extension ClassLoader 扩展类加载器
Sysetm ClassLoader 系统类加载器
类加载器的作用:
Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
获取Class文件对象:
/*
*
* 反射就是使用class文件对象,去使用该文件中的成员变量,构造方法,成员方法
* Person p = new Person();
* p...
*
*
* 使用反射,需要得到class文件对象,其实也就是得到Class类的对象
* Class类
* 成员变量 Field
* 构造方法:Constructor
* 成员方法:Method
*
*获取Class文件对象的方式
*1.Object类的getclass()方法
*2.数据类型的静态属性
*3.Class.forName()
*
*使用选择:
*开发环境下使用第三种方式,因为第三种是一个字符串,而不是一个具体的类名,可以配置到配置文件中
*
* */
public class Reflectdemo {
public static void main(String[] args) throws ClassNotFoundException {
//-----方式一--------
Person p = new Person();
Class c = p.getClass();
Person p2 = new Person();
Class c2 = p.getClass();
System.out.println(p == p2); //false
System.out.println(c == c2); //true Class文件对象都是同一个
//------方式二-------------
Class c3 = Person.class;
System.out.println(c == c3); //true
//-----方式三---------------
//带包名的路径demo.Person
Class c4 = Class.forName("demo.Person");
System.out.println(c == c4); //true
}
}
通过反射获取构造方法:
package demo;
public class Person {
String name;
int age;
String adress;
public Person() {
}
Person(String name,int age) {
this.name = name;
this.age = age;
}
public Person(String name,int age,String adress) {
this.name = name;
this.age = age;
this.adress = adress;
}
public void show() {
System.out.println("show");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", adress=" + adress + "]";
}
}
package demo_1;
import java.lang.reflect.Constructor;
/*通过反射获取构造方法并使用
*
* */
public class Reflect_demo {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//获取字节码文件对象:
Class c = Class.forName("demo.Person");
//获取构造方法
//public Constructor[] getConstructors() 所表示的类的所有公共构造方法
//public Constructor<?>[] getDeclaredConstructors() 所有构造方法
/*Constructor[] cons = c.getDeclaredConstructors();
for(Constructor con : cons) {
System.out.println(con);
}*/
//获取单个构造方法:
//public Constructor<T> getConstructor(Class<?>... parameterTypes)
//参数表示的是:你要获取的构造方法的构造参数个数和数据类型的Class字节码文件对象
Constructor con = c.getConstructor();
//使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例
Object obj = con.newInstance();
System.out.println(obj);
//person p = new person() system.out.println(p);上面那么多酒相当于这两句
}
}
通过反射获取构造方法,并且使用
package demo_1;
import java.lang.reflect.Constructor;
/*通过反射获取构造方法,并且使用
Person(String name,int age,String adress)
Person p = new Person("xiaoming",25,"nanjing");
System.out.println(p)*/
public class Reflect_demo2 {
public static void main(String[] args) throws Exception{
//获取字节码文件对象
Class c = Class.forName("demo.Person");
//获取带参数构造方法:
//public Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor con = c.getConstructor(String.class,int.class,String.class);
//通过带参构造方法创建对象
Object obj = con.newInstance("xiaoming",25,"nanjing");
System.out.println(obj);
}
}
//控制台返回
//Person [name=xiaoming, age=25, adress=nanjing]