反射的概述【理解】
是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调 用方法的一种机制。
由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。
通俗得讲,JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
获取Class类对象的三种方式
- 类名.class属性
- 对象名.getClass()方法
- Class.forName(全类名)方法
public static void main(String[] args) throws ClassNotFoundException {
Class<Student> c1=Student.class;
//使用类的class属性来获取该类对应的Class对象
System.out.println(c1);
Student s1=new Student();
//调用对象的getClass()方法,返回该对象所属类对应的Class对象
Class<?extends Student> c2=s1.getClass();
System.out.println(c2);
System.out.println(c1==c2);
//使用Class类中的静态方法forName(String className)
Class<?> c3=Class.forName("反射.Student");
System.out.println(c3);
}
}
反射获取构造方法并使用
Class类获取构造方法对象的方法
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException, IllegalAccessException, InvocationTargetException,
InstantiationException {
//获取Class对象
Class<?> c = Class.forName("com.itheima_02.Student");
//Constructor<?>[] getConstructors() 返回一个包含 Constructor对象的数组,
Constructor对象反映了由该 Class对象表示的类的所有公共构造函数
// Constructor<?>[] cons = c.getConstructors();
//Constructor<?>[] getDeclaredConstructors() 返回反映由该 Class对象表示的类
声明的所有构造函数的 Constructor对象的数组
Constructor<?>[] cons = c.getDeclaredConstructors();
for(Constructor con : cons) {
System.out.println(con);
}
System.out.println("--------");
//Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个
Constructor对象,该对象反映由该 Class对象表示的类的指定公共构造函数
//Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回
一个 Constructor对象,该对象反映由此 Class对象表示的类或接口的指定构造函数
//参数:你要获取的构造方法的参数的个数和数据类型对应的字节码文件对象
Constructor<?> con = c.getConstructor();
//Constructor提供了一个类的单个构造函数的信息和访问权限
//T newInstance(Object... initargs) 使用由此 Constructor对象表示的构造函数,
使用指定的初始化参数来创建和初始化构造函数的声明类的新实例
Object obj = con.newInstance();
System.out.println(obj);
// Student s = new Student();
// System.out.println(s);
}
反射获取构造方法并使用练习
public class ReflectDemo03 {
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException, IllegalAccessException, InvocationTargetException,
InstantiationException {
//获取Class对象
Class<?> c = Class.forName("com.itheima_02.Student");
//private Student(String name)
//Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
Constructor<?> con = c.getDeclaredConstructor(String.class);
//暴力反射
//public void setAccessible(boolean flag):值为true,取消访问检查
con.setAccessible(true);
Object obj = con.newInstance("林青霞");
System.out.println(obj);
}
}
此处setAccessible(boolean flag):值为true,作用取消访问检查,即可得到类的私有构造方法
反射获取成员变量并使用
public static void main(String[] args) throws ClassNotFoundException,
NoSuchFieldException, NoSuchMethodException, IllegalAccessException,
InvocationTargetException, InstantiationException {
//获取Class对象
Class<?> c = Class.forName("com.itheima_02.Student");
//Field[] getFields() 返回一个包含 Field对象的数组, Field对象反映由该 Class对
//Field[] getDeclaredFields() 返回一个 Field对象的数组,反映了由该 Class对象
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("--------");
//Field getField(String name) 返回一个 Field对象,该对象反映由该 Class对象表
//Field getDeclaredField(String name) 返回一个 Field对象,该对象反映由该
Field addressField = c.getField("address");
//获取无参构造方法创建对象
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
addressField.set(obj, "西安"); //给obj的成员变量addressField赋值为西安
System.out.println(obj);
}
}
Field类用于给成员变量赋值的方法
package 反射;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class Reflectdemo {
public static void main(String[] args) throws ClassNotFoundException,
NoSuchFieldException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
//获取Class对象
Class<?> c = Class.forName("反射.Student");
//Student s = new Student();
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
System.out.println(obj);
//s.name = "林青霞";
// Field nameField = c.getField("name"); //NoSuchFieldException:
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(obj, "林青霞");
System.out.println(obj);
//s.age = 30;
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(obj, 30);
System.out.println(obj);
//s.address = "西安";
}
}
反射获取成员方法并使用
反射的案例
运行配置文件中指定类的指定方法
- 案例需求
通过反射技术,向一个泛型为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);
}
}
运行配置文件中指定类的指定方法
- 案例需求
通过反射运行配置文件中指定类的指定方法
- 代码实现
Properties p=new Properties();
FileReader fr=new FileReader("A:\\Java黑马程序员\\java基础资料\\第二阶段资料\\二阶day15资料\\笔记\\test.txt");
p.load(fr);
Class C1=Class.forName(p.getProperty("Classname"));
Object o=C1.newInstance();
Method m=C1.getMethod(p.getProperty("Methodname"));
m.invoke(o);
我们可以使用配置文件来 此例为test.txt来运行程序。