反射
反射机制:动态获取信息,和动态调用对象方法的功能
作用:获取任意一个类中的所有信息 结合字节码文件动态创建对象
获取Class类对象的三种方式
- 类名.class属性
- 对象名.getclass()方法
- Class.forName(全类名)方法
全类名=包名+类名
public static void main(String[] args) throws ClassNotFoundException {
//1.Class.forName(全类名)全类名:包名加类名
Class clazz = forName("com.wedu.reflect.Student1");
System.out.println(clazz);
//2.类名.class属性
Class<Student1> clazz1 = Student1.class;
System.out.println(clazz1);
//3.对象名.getClass()方法
//先创建一个对象
Student1 student1 = new Student1();
Class clazz2 = student1.getClass();
System.out.println(clazz2);
System.out.println(clazz==clazz1);
System.out.println(clazz1==clazz2);
}
如何获取构造方法、成员方法、成员变量
get | 获取 |
set | 设置 |
Constructor | 构造方法 |
Field | 成员变量 |
Method | 方法 |
Paremeter | 参数 |
Modifiers | 修饰符 |
Declared | 私有的 |
反射练习
1. 利用反射和重载完成以下功能
1)创建Student类,类中有属性name和age并封装属性
2)重载Student的构造函数,一个是无参构造并,另一个是带两个参数的有参构造,要求在构造函数打印提示信息
3)创建带main函数的NewInstanceTest类,利用Class类得到Student对象
4)通过上述获取的Class对象分别调用Student有参函数和无参函数public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { //利用Class类得到Student对象 Class<?> c = Class.forName("com.wedu.reflect.Student"); //3)创建带main函数的NewInstanceTest类,利用Class类得到Student对象 // T newInstance(Object... initargs):根据指定的构造方法创建对象 // 4)通过上述获取的Class对象分别调用Studen无参函数 Constructor<?> constructor = c.getConstructor(); Object obj = constructor.newInstance(); //通过上述获取的Class对象分别调用Studen有参构造 Constructor<?> constructor1 = c.getConstructor(String.class, int.class); Object obj2 = constructor1.newInstance("ccx", 21); } } //1)创建Student类,类中有属性name和age并封装属性 class Student{ private String name; private int age; public Student() { System.out.println("Student的无参构造"); } public Student(String name, int age) { System.out.println("Student的有参构造"+"name"+name+"age"+age); // this.name = name; // this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
2. 利用通过反射修改私有成员变量
1. 定义PrivateTest类,有私有name属性,并且属性值为hellokitty,只提供name的getName的公有方法
2. 创建带有main方法ReflectTest的类,利用Class类得到私有的name属性
3. 修改私有的name属性值,并调用getName()的方法打印name属性值public class ReflectTest { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { //利用Class类得到私有的name属性 Class clazz = Class.forName("com.wedu.reflect.PrivateTest"); PrivateTest reflectTest = (PrivateTest) clazz.newInstance(); Field name = clazz.getDeclaredField("name"); //暴力反射,获取私有成员变量 name.setAccessible(true); //修改私有的name属性值, name.set(reflectTest,"Hellokitty"); //并调用getName()的方法打印name属性值 System.out.println(reflectTest.getName()); } } class PrivateTest{ //有私有name属性,并且属性值为hellokitty private String name = "hellokitty"; public PrivateTest() { } public PrivateTest(String name) { this.name = name; } //只提供name的getName public String getName() { return name; } }
3. 利用反射和File完成以下功能
1. 利用Class类的forName方法得到File类
2. 在控制台打印File类的所有构造器
3. 通过newInstance的方法创建File对象,并创建D:\mynew.txt文件public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { //1利用Class类的forName方法得到File类 Class clazz = Class.forName("java.io.File"); //2. 在控制台打印File类的所有构造器 Constructor[] de = clazz.getDeclaredConstructors(); for (Constructor constructor : de) { // System.out.println(constructor); } //获取一个File构造器 Constructor con = clazz.getConstructor(String.class); //通过newInstance的方法创建File对象 File file =(File) con.newInstance("D:\\mynew.txt"); //并创建D:\mynew.txt文件 Method m = clazz.getMethod("createNewFile"); m.invoke(file); }