java的反射机制
- 类加载器
- 反射
类加载器
类加载器的基本概念
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
类加载器的过程
加载----连接----初始化
类的加载时机
- 创建类的实例
- 访问类的静态变量,或者为静态变量赋值
- 调用类的静态方法
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
类加载器的分类
1.Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
2.Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
3.Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件
反射
反射的基本概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
获取字节码文件对象的三种方法
A:Object类的getClass()方法
B:数据类型的静态class属性
C:Class类的静态方法forName()
package com.wy.reflect1;
public class Student {
private String name;
int age;
public String gender;
public Student(){}
Student(String name){
this.name = name;
}
protected Student(String name,int age){
this.name = name;
this.age = age;
}
private Student(String name,int age,String gender){
this.name = name;
this.age = age;
this.gender = gender;
}
public void show(){
System.out.println("public show");
}
protected void proShow(){
System.out.println("protected show");
}
void voShow(){
System.out.println("void show");
}
private void priShow(){
System.out.println("private show");
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", gender=" + gender + "]";
}
}
首先定义了一个Student类,下面的代码是使用三种方法获得Student的字节码文件对象。
package com.wy.reflect1;
public class ClassGetTest {
public static void main(String[] args) {
//获取字节码文件对象的第一种方式
//Object类的getClass()方法
Student s = new Student();
Class cla1 = s.getClass();
System.out.println(cla1);
//获取字节码文件对象的第二种方式
//数据类型的静态class属性
Class cla2 = Student.class;
System.out.println(cla2);
System.out.println("The first and the second is equals? ");
System.out.println(cla1 == cla2);
//获取字节码文件的第三种方式
//Class类的静态方法forName()
try {
Class cla3 = Class.forName("com.wy.reflect1.Student");
System.out.println(cla3);
System.out.println("The first and the third is equals? ");
System.out.println(cla1 == cla3);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
反射的使用步骤
class字节码文件对象 -- 去得到对应的成员对象 -- 通过该成员的对象调用方法使用。
**成员变量 Field
构造方法 Constructor
成员方法 Method**
*凡是加declared,就是什么类型都可以获取的;
凡是方法后面加s的都是获取多个*
通过反射获取构造方法
package com.wy.reflect1;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ConstructorTest {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象的第一种方式
// Object类的getClass()方法
Student s = new Student();
Class class1 = s.getClass();
//1.通过反射获取构造方法 public Constructor[] getConstructors() 获取公共的构造方法 public
Constructor[] cons = class1.getConstructors();
System.out.println("getConstructors----------results are ");
for (Constructor con : cons) {
System.out.println(con);
}
//利用构造方法创建对象
Constructor con = cons[0];
try {
Student stu = (Student) con.newInstance();
stu.show();
} catch (Exception e) {
e.printStackTrace();
}
//Constructor[] getDeclaredConstructors() 获取所有的构造方法(包括私有) public
Constructor[] cons2 = class1.getDeclaredConstructors();
System.out.println("getDeclaredConstructors----------------results are ");
for (Constructor c : cons2) {
System.out.println(c);
}
cons2[0].setAccessible(true);
//取消访问修饰符限制的构造器创建对象
Student stu2 = (Student) cons2[0].newInstance("wy",18,"woman");
stu2.proShow();
//Constructor getConstructor(Class... parameterTypes)
Constructor con3 = class1.getDeclaredConstructor(String.class, int.class, String.class);
System.out.println("getConstructor(String.class,int.class, String.class)-----------results are ");
System.out.println(con3);
//取消访问修饰符的限制
con3.setAccessible(true);
//利用取消访问修饰符的构造器创建对象
Student stu3 = (Student) con3.newInstance("zl",28,"man");
System.out.println(stu3);
}
}
通过反射获取成员变量
package com.wy.reflect1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class FieldTest {
/*
* private String name;
* int age;
* public String gender;
*/
public static void main(String[] args) throws Exception {
Class cla2 = Student.class;
Constructor con = cla2.getConstructor();
Student stu = (Student) con.newInstance();
/*
public Field[] getFields()获取公有的成员变量
public Field[] getDeclaredFields()获取全部的成员变量,包括私有
public Field getDeclaredField(String name) 传入变量名称返回指定的成员变量对象,包括私有
public Field getField(String name)传入变量名称返回指定的成员变量对象,仅可获取共有的
public void set(Object obj,Object value)给一个对象的一个字段设置一个值
*/
//public Field[] getFields()获取公有的成员变量
Field[] fields = cla2.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("------------------");
//public Field[] getDeclaredFields()获取全部的成员变量,包括私有
Field[] fields2 = cla2.getDeclaredFields();
for (Field field : fields2) {
System.out.println(field);
}
//public Field getDeclaredField(String name) 传入变量名称返回指定的成员变量对象,包括私有
Field f = cla2.getDeclaredField("name");
f.setAccessible(true);
f.set(stu, "wangying");
System.out.println(stu);
}
}
通过反射获取成员方法
package com.wy.reflect1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class MethodTest {
public static void main(String[] args) throws Exception {
Class cla3 = Class.forName("com.wy.reflect1.Student");
Constructor con = cla3.getDeclaredConstructor(String.class,int.class);
con.setAccessible(true);
Student stu = (Student) con.newInstance("zl",18);
Method[] methods = cla3.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
Method m = cla3.getDeclaredMethod("proShow");
//调用这个方法
/*
* public Object invoke(Object obj,Object... args)
* 参数1:执行m2这个方法的对象
* 参数2:执行m2这个方法的时候,需要传入的参数
*/
m.invoke(stu);
}
}
java的反射到此……