java反射基础思想
反射概述
反射就是动态加载对象,并对对象进行剖析。在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动态获取信息以及动态调用对象方法的功能成为Java反射机制。
获取Class类对象的三种方式
- 类名.class属性
- 对象名.getClass()方法
- Class.forName(全类名)方法
示例代码
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//使用类的class属性来获取该类对应的Class对象
Class<Student> c1 = Student.class;
System.out.println(c1);
Class<Student> c2 = Student.class;
System.out.println(c1 == c2);
System.out.println("--------");
//调用对象的getClass()方法,返回该对象所属类对应的Class对象
Student s = new Student();
Class<? extends Student> c3 = s.getClass();
System.out.println(c1 == c3);
System.out.println("--------");
//使用Class类中的静态方法forName(String className)
Class<?> c4 = Class.forName("com.itheima_02.Student");
System.out.println(c1 == c4);
}
}
如何实现Java的反射?
1、反射获取构造方法并使用
方法分类
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor getConstructor(Class<?>… parameterTypes) | 返回单个公共构造方法对象 |
Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 返回单个构造方法对象 |
Constructor类用于创建对象的方法
方法名 | 说明 |
---|---|
T newInstance(Object…initargs) | 根据指定的构造方法创建对象 |
2、反射获取成员变量并使用
方法分类
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
Field类用于给成员变量赋值的方法
方法名 | 说明 |
---|---|
voidset(Object obj,Object value) | 给obj对象的成员变量赋值为value |
3、反射获取成员方法并使用
方法分类
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class<?>… parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name, Class<?>… parameterTypes) |
Method类用于执行方法的方法
方法名 | 说明 |
---|---|
Objectinvoke(Object obj,Object… args) | 调用obj对象的成员方法,参数是args,返回值是Object类型 |
小结:具体实现核心操作
1、通过一个全限类名创建一个对象
Class.forName(“全限类名”); 例如:com.mysql.jdbc.Driver Driver类已经被加载到 jvm中,并且完成了类的初始化工作就行了
类名.class; 获取Class<?> clz 对象
对象.getClass();
2、获取构造器对象,通过构造器new出一个对象
Clazz.getConstructor([String.class]);
Con.newInstance([参数]);
3、通过class对象创建一个实例对象(就相当与new类名()无参构造器)
Cls.newInstance();
4、通过class对象获得一个属性对象
Field c=cls.getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
Field c=cls.getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的声明字段
5、通过class对象获得一个方法对象
Cls.getMethod(“方法名”,class……parameaType);(只能获取公共的)
Cls.getDeclareMethod(“方法名”);(获取任意修饰的方法,不能执行私有)
M.setAccessible(true);(值为true,取消访问检查)
6、让方法执行
1). Method.invoke(obj实例对象,obj可变参数);-----(是有返回值的)
反射的案例
1、反射练习之越过泛型检查
-
案例需求
- 通过反射技术,向一个泛型为Integer的集合中添加一些字符串数据
代码实现
public class ReflectTest01 {
public static void main(String[] args) throws Exception {
//创建集合
ArrayList<Integer> array = new ArrayList<Integer>();
// array.add(10);
// array.add(20);
// array.add("hello");
Class<? extends ArrayList> c = array.getClass();
Method m = c.getMethod("add", Object.class);
m.invoke(array,"hello");
m.invoke(array,"world");
m.invoke(array,"java");
System.out.println(array);
}
}
运行配置文件中指定类的指定方法
-
案例需求
- 通过反射运行配置文件中指定类的指定方法
代码实现
public class ReflectTest02 {
public static void main(String[] args) throws Exception {
//加载数据
Properties prop = new Properties();
FileReader fr = new FileReader("myReflect\\class.txt");
prop.load(fr);
fr.close();
/*
className=com.itheima_06.Student
methodName=study
*/
String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");
//通过反射来使用
Class<?> c = Class.forName(className);//com.itheima_06.Student
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
Method m = c.getMethod(methodName);//study
m.setAccessible(true);//值为true,取消访问检查
m.invoke(obj);
}
}