目录
什么是反射
从编程的角度来说 :
从生活的角度来说 :
Class类
记住一句话:
获取Class对象的三种方法 :
通过Class.forName("包名.类名")获取class对象 (方法一)
通过类名.class获取Class对象(方法二)
通过 对象.class 获取Class对象
获取Class类总结 :
反射Api使用
newInstance()使用
getConstructor(型参类型.class,型参类型.class,…)
Field
getFields();
getDeclaredFields() ;
什么是反射
从编程的角度来说 :
反射就是把java类中的各种成分映射成一个个的Java对象
通过反射,在程序运行时,可以动态获取一个类的所有属性,方法,包括(私有的)!!!!
从生活的角度来说 :
1.当你站在镜子前时,你可以看到自己的外貌:你的发型、穿着和身体状况等。这就类似于在 Java 中使用反射来查看一个类的信息,比如类的名字、它的方法、字段和其他外部特征。
2.在现实生活中,你可能会在看镜子后决定改变某些东西,比如换一种发型或换一件衣服。在 Java 反射中,这就相当于改变对象的状态或行为,例如修改一个对象的属性值或调用它的某个方法。
Class类
记住一句话:
只要是类,他就有class对象,反射都是基于class对象去操作的!!!
每个类都有一个 Class 对象,它用来创建这个类的所有对象,反过来说,每个类的所有对象都会关联同一个 Class 对象(对于数组来说,维数、类型一致的数组的 Class 对象才是相同的) , 每个对象的创建都依赖于 Class 对象的是否创建,Class 对象的创建发生在类加载(java.lang.ClassLoader)的时候。
获取Class对象的三种方法 :
通过Class.forName("包名.类名")获取class对象 (方法一)
第一步 :
创建一个Student类
package com.xr.ademo;// 第一步 : 创建一个Student 类,有属性,有构造方法,有getter,setter方法(标准的javaBean类)
public class Student {private String name; // 姓名private String sex; // 年龄/*无参构造*/public Student() {}/*全参构造*/public Student(String name, String sex) {this.name = name;this.sex = sex;}/*属性的getter,setter方法*/public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}
}
第二步:
定义一个测试类,并使用Class.forNam();方法
package com.xr.aDemo;
import java.lang.reflect.Method;public class StudentTest {public static void main(String[] args) throws Exception {//第二步: 通过Class.forName()方法获取class对象// 使用forName方法时需要抛出异常,因为肯能获取的类为空!!!!Class<?> clazz = Class.forName("com.xr.aDemo.Student");// 获取类中的所有公共方法,不包括私有方法Method[] methods = clazz.getMethods();//循环遍历所有公共方法for (Method method : methods) {//输出公共方法的名称System.out.println(method.getName());}}
}
forName(); 方法的参数就是你所要获取的类路径
上面的forName参数就是 com.xr.aDemo.Student
最后输出结果为 :
为什么除了我们自己定义的get,set方法还有其他方法名称呢???
因为我们自己定义的类,(只要是类)都会隐式继承父类(Object),所以有其他的方法,指向的为父类的方法
通过类名.class获取Class对象(方法二)
第一步:
还是接着上面方法1定义的Student类使用
第二步:
编写测试类使用类名.class获取class对象
package com.xr.aDemo;
import java.lang.reflect.Method;public class StudentTest {public static void main(String[] args) {//第二步: 通过类名.class获取Class对象Class<Student> studentClass = Student.class;// 获取类中的所有公共方法 Method[] methods = studentClass.getMethods();// 循环遍历公共方法for (Method method : methods) {// 输出方法名称System.out.println(method.getName());}}
}
最后运行结果为:
通过 对象.class 获取Class对象
第一步 :
还是接着上面方法1定义的Student类使用
第二步 :
创建一个测试类,并使用 对象.class 获取Class独享
package com.xr.aDemo;
import java.lang.reflect.Method;public class StudentTest {public static void main(String[] args) {//第二步: 创建Student对象Student student = new Student();//第三步: 通过对象.getClass获取Class对象Class<? extends Student> clazz = student.getClass();//第四步: 获取所有的公共方法Method[] methods = clazz.getMethods();//第五步: 遍历功公共方法for (Method method : methods) {System.out.println(method.getName());}}
}
最后运行结果:
获取Class类总结 :
这三种方式都是获取Class对象的方法,但一般推荐使用的是第一种方法【Class.forName()】方法。
因为第二种方法【类名.class】方法需要导包,而第三种方法【对象.class】方法需要先创建对象之后,在通过对象名称的class获取Class对象,但是设想一下,我都有了Student对象,已经有了他的属性和方法,我还需要反射获取他嘛,所以推荐第一种方法
反射Api使用
newInstance()使用
newInstance()方法的作用 : 动态创建类的对象,动态创建类的实例
第一步重新创建一个Student类
package com.xr.aDemo;// 第一步 : 创建一个Student 类,有属性,有构造方法,有getter,setter方法(标准的javaBean类)
// 还有其他方法,并重新写了ToString()方法
public class Student {private String name; //姓名private int age; // 年龄private float weight; // 体重private static final double PI = 3.14; // 圆周率/*构造方法*/public Student() {}public Student(String name, int age, float weight) {this.name = name;this.age = age;this.weight = weight;}public Student(String name, Float weight) {this.name = name;this.age = 18;this.weight = weight;}/*getter,setter方法*/public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public float getWeight() {return weight;}public void setWeight(float weight) {this.weight = weight;}/*其他方法*/public void hello() {System.out.println("你好!");}private void sleep() {System.out.println("睡觉了!");}public void sayHello(String who) {System.out.println("你好," + who);}public int sum(int i, int j) {return i + j;}/*重写toString方法*/@Overridepublic String toString() {return this.getName()+","+this.getAge()+","+this.getWeight() ;}
}
第二步 :
编写测试类,使用newInstance()方法创建对象的实例
package com.xr.aDemo;
import java.lang.reflect.Method;public class StudentTest {public static void main(String[] args) throws Exception {// 第二步,通过class.forName()方法获取Class对象,使用forName()需要抛出异常Class<?> clazz = Class.forName("com.xr.aDemo.Student");//第三步: 通过Class对象的newInstance()方法来实例化对象Student student = (Student) clazz.newInstance();//第四步: 既然有了student对象,就可以随便调用student类里面的方法了student.hello();student.sayHello("张三");}
}
最后调用方法的结果:
getConstructor(型参类型.class,型参类型.class,…)
getCounstructor()的作用:获取有参数的构造方法信息
第一步:
还是接着上面的Student类使用
第二步:
创建测试类,使用 getConstructor(); 获取重载构造方法,并实例化
package com.xr.aDemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;public class StudentTest {public static void main(String[] args) throws Exception {// 第二步,通过class.forName()方法获取Class对象,使用forName()需要抛出异常Class<?> clazz = Class.forName("com.xr.aDemo.Student");// 第三步, 通过getConstructor()方法获取构造器对象//这里的值是与构造器参数类型一致的参数列表的class对象Constructor<?> constructor = clazz.getConstructor(String.class, int.class, float.class);// 第四步, 通过构造器对象获取实例对象Object obj = constructor.newInstance("张三", 18, 60.0f);//转型成Student对象Student student = (Student) obj;//输出student对象System.out.println(student);}
}
注意:
getConstructor()方法里面的参数,一定要与你定义的构造方法中的参数类型对应,并获取对应的类型class对象,将对应的类型Class对象做为参数
这句代码中的参数,与下面截图对应的构造方法类型对应
Constructor<?> constructor = clazz.getConstructor(String.class, int.class, float.class);
最后运行的结果为:
这个方法总结:
重点:
getConstructor()这个方法说白了就是获取有参的构造方法的实例;
而newInstance()这个方法直接获取无参的构造方法的实例;
Field
getFields();
获取所有公共的字段;
还是接着上面的student类,但是增加一个公共属性
第二步:
通过getFields()方法获取所有公共属性
package com.xr.aDemo;
import java.lang.reflect.Field;public class StudentTest {public static void main(String[] args) throws Exception {// 第二步,通过class.forName()方法获取Class对象,使用forName()需要抛出异常Class<?> clazz = Class.forName("com.xr.aDemo.Student");//第三步: 通过getFields()方法获取所有公共属性Field[] field = clazz.getFields();//第四步: 循环遍历所有属性for (Field f : field) {System.out.println("属性名:" + f.getName());}}
}
最后结果:
getDeclaredFields() ;
获取所有的字段(是所有,不管你是公开还是私有.......等等)
第一步:
还是那个Studnet类,并增加了一个公共字段
第二步 :
使用getDeclaredFields()方法获取所有属性
package com.xr.aDemo;
import java.lang.reflect.Field;public class StudentTest {public static void main(String[] args) throws Exception {// 第二步,通过class.forName()方法获取Class对象,使用forName()需要抛出异常Class<?> clazz = Class.forName("com.xr.aDemo.Student");//第三步: 通过getFields()方法获取所有属性(不管是什么访问的修饰符)Field[] field = clazz.getDeclaredFields();//第四步: 循环遍历所有属性for (Field f : field) {System.out.println("属性名:" + f.getName());}}
}
最后的结果为:
----------------------待更新