反射:框架设计的灵魂,将类的各个组成部分封装为其他对象,这就是反射机制。
反射的好处:
1.可以在程序运行过程中,操作这些对象
2.可以解耦,提高程序的可扩展性
框架:半成品软件。可以在框架的基础上进行软件开发,简化编码的动作。
Java代码在计算机中经历的三个阶段:
① Source源代码阶段:.java 文件 ----> .class字节码文件
② Class类对象阶段:类加载器ClassLoader将字节码文件加载进内存,在内存中,字节码文件由类Class的对象描述,Class对象中又包含类数组Field[] fields描述成员变量,类数组Constructor[] cons描述构造方法,类数组Method[] methods描述成员方法
③ Runtime运行时阶段:创建对象
将成员变量封装为Field对象,将构造方法封装为Constructor对象,将成员方法构造为Method对象就是反射的过程。
IDE中键盘打出一个对象会自动提示可用的方法就是用到了反射机制,在内存中已经将该对象所有的成员方法提取出来封装到Method数组中,在IDE中打出对象后自动提取出Method数组的内容并显示到列表中。
获取Class对象的方式:
1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
* 多用于配置文件,将类名定义在配置文件中,读取文件,加载类
2. 类名.class:通过类名的属性class获取
* 多用于参数的传递
3. 对象.getClass():该方法在Object类中定义的,所有类都有该方法
* 多用于已经存在对象时
1 /* Person.java */ 2 3 public class Person { 4 private String name = "name的默认值"; 5 private int age; 6 public String test = "test的默认值"; 7 8 public Person() {} 9 10 public Person(String name, int age) { 11 this.name = name; 12 this.age = age; 13 } 14 15 public String getName() { 16 return name; 17 } 18 public void setName(String name) { 19 this.name = name; 20 } 21 22 public int getAge() { 23 return age; 24 } 25 public void setAge(int age) { 26 this.age = age; 27 } 28 29 public void eat() { 30 System.out.println("吃了一口"); 31 } 32 33 public void eat(String food) { 34 System.out.println("吃了一口" + food); 35 } 36 37 @Override 38 public String toString() { 39 return "Person {" 40 + "name=" + name + ", " 41 + "age=" + age + ", " 42 + "test=" + test 43 + "}"; 44 } 45 }
1 public class ReflectDemo_1 { 2 public static void main(String[] args) throws Exception { 3 // 1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象 4 Class cls1 = Class.forName("domain.Person"); 5 System.out.println(cls1); 6 7 // 2. 类名.class:通过类名的属性class获取 8 Class cls2 = Person.class; 9 System.out.println(cls2); 10 11 // 3. 对象.getClass():该方法在Object类中定义的,所有类都有该方法 12 Person person = new Person(); 13 Class cls3 = person.getClass(); 14 System.out.println(cls3); 15 16 // 比较三个类 17 System.out.println(cls1 == cls2); 18 System.out.println(cls1 == cls3); 19 System.out.println(cls2 == cls3); 20 } 21 }
三个class对象相同,由此可知,同一个.class字节码文件在一次运行过程中只会被加载一次,无论通过哪一种方法获得的Class对象都是同一个
Class对象功能:
1. 获取成员变量
* Field[] getFields():获取所有public修饰的成员变量
* Field[] getField(String name):获取所有指定名称的public修饰的成员变量
* Field[] getDeclaredFields():获取所有成员变量,不考虑修饰符
* Field[] getDeclaredField(String name):获取所有指定名称的成员变量,不考虑修饰符
* setAccessible(true):忽略访问权限修饰符的安全检查,也叫暴力反射
(之前学习类时说到私有成员无法在类外访问,但在反射这里没有私有公有的概念,但是要获得私有成员具体的值需要用到暴力反射)
2. 获取构造方法
* Constructor<?>[] getConstructs()
* Constructor<T> getConstruct(类<?>... parameterTypes)
* Constructor<?>[] getDeclaredConstructs()
* Constructor<T> getDeclaredConstruct(类<?>... parameterTypes)
3. 获取成员方法
* Method[] getMethods()
* Method getMethod(String name, 类<?>... parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name, 类<?>... parameterTypes)
4. 获取类名
* String getName()
成员变量Field
* 常见操作
1. 获取值:get(Object obj)
2. 设置值:void set(Object obj, Object value)
1 public class ReflectDemo_2 { 2 public static void main(String[] args) throws Exception { 3 // 获取Person的Class对象 4 Class personClass = Person.class; 5 6 // 获取成员变量 7 // * Field[] getFields():获取所有public修饰的成员变量 8 Field[] fields = personClass.getFields(); 9 for(Field field : fields) { 10 System.out.println(field); 11 } 12 System.out.println("------------------------------------------"); 13 // * Field[] getField(String name):获取所有指定名称的public修饰的成员变量 14 Field test = personClass.getField("test"); 15 System.out.println(test); 16 // 获取成员变量test的值 17 Person p = new Person(); 18 Object value_test1 = test.get(p); 19 System.out.println(value_test1); 20 // 设置成员变量test的值 21 test.set(p, "test更新后的值"); 22 Object value_test2 = test.get(p); 23 System.out.println(value_test2); 24 System.out.println(p); 25 System.out.println("------------------------------------------"); 26 // * Field[] getDeclaredFields() 27 Field[] declaredFields = personClass.getDeclaredFields(); 28 for (Field declaredField : declaredFields) { 29 System.out.println(declaredField); 30 } 31 System.out.println("------------------------------------------"); 32 // * Field[] getDeclaredField(String name) 33 Field name = personClass.getDeclaredField("name"); 34 System.out.println(name); 35 // 忽略访问权限修饰符的安全检查,也叫暴力反射 36 name.setAccessible(true); 37 Object value_name1 = name.get(p); 38 System.out.println(value_name1); 39 } 40 }
构造方法Constructor
* 常见操作
创建对象:T newInstance(Object...initargs)
1 public class ReflectDemo_3 { 2 public static void main(String[] args) throws Exception { 3 // 获取Person的class对象 4 Class personClass = Person.class; 5 6 // 获取构造方法 7 // * Constructor<T> getConstruct(类<?>... parameterTypes) 8 // 带参数的构造方法 9 Constructor constructor = personClass.getConstructor(String.class, int.class); 10 System.out.println(constructor); 11 Object person = constructor.newInstance("zs", 15); 12 System.out.println(person); 13 System.out.println("------------------------------------------"); 14 // 空构造方法 15 Constructor constructor_null = personClass.getConstructor(); 16 Object person_null = constructor_null.newInstance(); 17 System.out.println(person_null); 18 // 更简单的使用空构造函数的方法,但此方法已被弃用 19 Object obj = personClass.newInstance(); 20 System.out.println(obj); 21 } 22 }
成员方法Method
* 常见操作
执行方法:Object invoke(Object obj, Object args)
* 获取方法名
String getName()
1 public class ReflectDemo_4 { 2 public static void main(String[] args) throws Exception { 3 // 获取Person的class对象 4 Class personClass = Person.class; 5 6 // 获取指定名称的成员方法 7 Method eat_method = personClass.getMethod("eat"); 8 Person p = new Person(); 9 eat_method.invoke(p); 10 Method eat_method_food = personClass.getMethod("eat", String.class); 11 eat_method_food.invoke(p, "饭"); 12 System.out.println("------------------------------------------"); 13 // 获取所有public修饰的方法 14 Method[] methods = personClass.getMethods(); 15 for (Method method : methods) { 16 System.out.println(method); 17 // 获取方法名:getName() 18 System.out.println(method.getName()); 19 } 20 // 获取类名:getName() 21 System.out.println(personClass.getName()); 22 } 23 }
标签:反射,Java,name,System,String,println,public,out From: https://www.cnblogs.com/yyyz888/p/16907496.html