反射
1. 什么是反射
动态语言 : 在运行时代码可以根据某些条件改变自身结构
java正是因为有了反射 , 才可以称为"准动态语言"
2.反射相关的主要API
3.Class类
3.1 Class类的理解
3.2 获取Class实例的四种方式
3.3 Class实例可以是哪些结构 ?
4. 代码
//使用反射创建对象 @Test public void test2()throws Exception{ Class clazz = Person.class; //1.通过反射创建person Constructor constructor = clazz.getConstructor(String.class, int.class); Object arthur = constructor.newInstance("Arthur",24); Person person = (Person) arthur; System.out.println(person); //2.调用属性 Field age = clazz.getDeclaredField("age"); age.set(person,25); System.out.println(person); //3.调用方法 Method show = clazz.getDeclaredMethod("show"); String str = (String) show.invoke(person); System.out.println(str); //通过反射调用私有的结构 : 构造器 , 属性, 方法 //构造器 Constructor constructor1 = clazz.getDeclaredConstructor(String.class); constructor1.setAccessible(true); Person tom = (Person) constructor1.newInstance("Tom"); System.out.println(tom); //属性 Field name = clazz.getDeclaredField("name"); name.setAccessible(true); name.set(tom,"Arthur"); System.out.println(tom); //方法 Method showNation = clazz.getDeclaredMethod("showNation", String.class); showNation.setAccessible(true); String str1 = (String) showNation.invoke(tom,"China"); System.out.println(str1); } //反射的动态性 @Test public void test3() throws ClassNotFoundException, InstantiationException, IllegalAccessException { int i = new Random().nextInt(3); String path = ""; switch(i){ case 0: path = "java.lang.Object"; break; case 1: path = "java.util.Date"; break; case 2: path = "com.atguigu.java.Reflection.Person"; break; } Object instance = getInstance(path); System.out.println(instance); } public Object getInstance(String path) throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class clazz = Class.forName(path); return clazz.newInstance(); }
public class ReflectionTest2 { //调用运行时类 指定的属性 @Test public void test1() throws IllegalAccessException, InstantiationException, NoSuchFieldException { Class<Person> clazz = Person.class; //1.创建运行时类的对象 Person person = clazz.newInstance(); //2.获取要操作的属性 Field name = clazz.getDeclaredField("name"); //3.保证当前属性是可访问的 name.setAccessible(true); //4.通过属性 , 设置指定对象的值 name.set(person,"Tom"); //value1 : 要设置的对象 , value2:设置的值 System.out.println(person); } //调用运行时类方法 @Test public void test2() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Class clazz = Person.class; //1.创建对象 Object person = clazz.newInstance(); //2.获取调用的方法 //value1: 方法名称 , value2:方法的形参类型 Method show = clazz.getDeclaredMethod("showNation",String.class); //3.声明 show.setAccessible(true); //4.通过方法调对象 , 来调用此方法 //invoke()的返回值 即为被调用方法的返回值 Object china = show.invoke(person, "China"); System.out.println(china); System.out.println("************************调用静态方法****************************"); Method showDance = clazz.getDeclaredMethod("showDance"); showDance.setAccessible(true); //静态方法 , 直接传入当前对象 //没有返回值就为null Object dance = showDance.invoke(Person.class); //Object dance = showDance.invoke(null); 也可 System.out.println(dance); } //调用运行时类的构造器 @Test public void test3() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Class clazz = Person.class; Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class); constructor.setAccessible(true); Object tom = constructor.newInstance("Tom",29); System.out.println(tom); } }
public class Person{ private String name; public int age; public Person() { } private Person(String name) { this.name = name; } public Person(int age) { this.age = age; } public Person(String name, int age) { this.name = name; this.age = age; } private String getName() { return name; } private void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } public String show(){ return "I'm Chinese"; } private String showNation(String nation){ System.out.println("My nationality is "+nation); return nation; } private static void showDance(){ System.out.println("dancing with your ghost "); } }
4.1 利用发射读取配置文件
4.2 反射获取运行时类父类的泛型
5. 总结
从代码角度来说 : 没有反射以前 , 只能通过new 来创建对象 , 调用属性和方法 , 有了反射以后 , 可通过API动态的创建对象及调用属性和方法(不用写死了).
从逻辑角度来说 : 万物皆对象 , 类本身也是对象 !