
反射:将类的各个组成部分封装为其他对象,这就是反射机制
好处:
- 可以在程序运行过程中,操作这些对象
- 可以解耦,提高程序的可扩展性
获取Class对象的方式
- Class.forName(”全类名”):将字节码文件加载进内存,返回Class对象
多用于配置文件,将类名定义在配置文件中。读取文件,加载类
- 类名.Class:通过类名的属性Class获取
多用于参数的传递
- 对象.getclass():getclass()方法在Object类中定义着
多用于对象的获取字节码的方式
Class对象功能
获取功能
1.获取成员变量们
Field[ ] getFields( ) :获取所有public修饰的成员变量
Field getField(String name) :获取指定名称的public修饰的成员变量
Field[ ] getDeclaredFields( ) :获取所有的成员变量,不考虑修饰符
Field getDeclaredField(String name)
2.获取构造方法们
Constructor<?>[ ] getConstructors( )
Constructor
Constructor
Constructor<?>[ ] getDeclaredConstructors( )
3.获取成员方法们
Method[ ] getMethods( )
Method getMethod(String name,类<?>… parameterTypers)
Method[ ] getDeclaredMethods( )
Method getDeclaredMethod(String name,类<?>… parameterTypers)
4**.**获取类名
String getName( )
**
Field:成员变量
操作
1.设置值
void set(Object obj,Object value)
2.获取值
get(Object obj)
3.忽略访问权限修饰符的安全检查
setAccessible(true):暴力反射
Person类:
package HeiMa.Reflect;/*@create 2020--12--24--20:53*/public class Person {private String name;private int age;public String a;protected String b;String c;private String d;public Person() {}public Person(String name, int age, String a, String b, String c, String d) {this.name = name;this.age = age;this.a = a;this.b = b;this.c = c;this.d = d;}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 String getA() {return a;}public void setA(String a) {this.a = a;}public String getB() {return b;}public void setB(String b) {this.b = b;}public String getC() {return c;}public void setC(String c) {this.c = c;}public String getD() {return d;}public void setD(String d) {this.d = d;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", a='" + a + '\'' +", b='" + b + '\'' +", c='" + c + '\'' +", d='" + d + '\'' +'}';}public void eat() {System.out.println("eat...");}public void eat(String food) {System.out.println("eat..."+ food);}}
获取成员变量:
package HeiMa.Reflect;/*@create 2020--12--24--20:55*/import java.lang.reflect.Field;public class ReflectDemo {public static void main(String[] args) throws Exception {//获取person的class对象Class personClass = Person.class;// Field[] getFields()获取所有public修饰的成员变量Field[] fields = personClass.getFields();for (Field field : fields) {System.out.println(field);}System.out.println("------------------");Field a = personClass.getField("a");//获取成员变量a的值Person person = new Person();Object o = a.get(person);System.out.println(o);a.set(person, "张三");System.out.println(person);System.out.println("===================");Field[] declaredFields = personClass.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println(declaredField);}//field getDeclaredField(String name)Field d = personClass.getDeclaredField("d");//忽略访问权限修饰符的安全检查d.setAccessible(true);//暴力反射Object o1 = d.get(person);System.out.println(o1);}}
Constructor:构造方法
创建对象:
T newInstance(Object……initargs)
如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance
获取构造方法:
package HeiMa.Reflect;/*@create 2020--12--24--20:55*/import java.lang.reflect.Constructor;import java.lang.reflect.Field;public class ReflectDemo2 {public static void main(String[] args) throws Exception {//获取person的class对象Class personClass = Person.class;Constructor constructor = personClass.getConstructor(String.class, int.class,String.class,String.class,String.class,String.class);System.out.println(constructor);//创建对象Object person = constructor.newInstance("张三", 28,"a","b","c","d");System.out.println(person);System.out.println("---------------------");Constructor constructor1 = personClass.getConstructor();System.out.println(constructor1);//创建对象Object o = constructor1.newInstance();System.out.println(o);Object o1 = personClass.newInstance();System.out.println(o1);}}
Method:方法对象
执行方法
Object invoke(Object obj,Object…… args)
获取方法名称:
String getName:获取方法名
获取方法对象及方法名:
package HeiMa.Reflect;/*@create 2020--12--24--20:55*/import java.lang.reflect.Constructor;import java.lang.reflect.Method;public class ReflectDemo3 {public static void main(String[] args) throws Exception {//获取person的class对象Class personClass = Person.class;//获取指定名称的方法Method eat = personClass.getMethod("eat");Person p = new Person();//执行方法eat.invoke(p);Method eat1 = personClass.getMethod("eat", String.class);//执行方法eat1.invoke(p, "饭");System.out.println("-----------");//获取所有public修饰的方法Method[] methods = personClass.getMethods();for (Method method : methods) {System.out.println(method);System.out.println(method.getName());}//获取类名String name = personClass.getName();System.out.println(name);}}
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个
Java反射机制是Java中底层的一个功能,就是通过这个机制可以进行对象的灵活的调用和处理
在后期学习中会用到反射的相关的内容,但是都是底层的理解,比如:文件的加载,spring框架底层……
目前我们讲反射是讲解反射的使用
Java中提供了一个api - Class用于反射机制的一个类
是在Java.lang包下的,不需要导包
当前案例演示利用反射的机制获取对象的属性
package Test25_Demo.TestDemo2;/*@create 2020--12--18--10:14*/import org.junit.Test;public class ReflectDemo {//新建对象的获取直接使用反射获取 - 不适用new//单元测试@Testpublic void test1() {//已知明确的类型,获取Class对象Class clazz = Student.class;System.out.println(clazz);//class Test25_Demo.TestDemo2.Student}@Testpublic void test2() {//已知对象获取class对象Student s = new Student();Class clazz = s.getClass();//getClass()是顶级父类Object中的方法System.out.println(clazz);//class Test25_Demo.TestDemo2.Student}@Testpublic void test3() throws ClassNotFoundException {//完全限定名(包名.类名),获取Class对象 - 比较常用 - 安全String className = "Test25_Demo.TestDemo2.Student";//forName()返回这个地址值所对应的类Class<?> aClass = Class.forName(className);System.out.println(aClass);//class Test25_Demo.TestDemo2.Student}//测试结果:通过不同的反射获取的对象是同一个@Testpublic void test4() throws ClassNotFoundException {Class clazz1 = Student.class;Student s1 = new Student();Class clazz2 = s1.getClass();String className = "Test25_Demo.TestDemo2.Student";Class<?> aClass = Class.forName(className);//比较System.out.println(clazz1 == clazz2);//trueSystem.out.println(clazz2 == aClass);//trueSystem.out.println(clazz1 == aClass);//true}}
package Test25_Demo.TestDemo2;/*@create 2020--12--18--10:14*/import org.junit.Test;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;/*** 通过Java反射机制构建对象的测试 - 这些操作平时只要我们创建对象,内存中就偷偷的帮我们做了* 步骤:* 1.创建该类的Class对象* 2.利用Class对象去创建类对象* 3.利用Class对象中的newInstance方法创建对象,类中有公共的无参构造方法* 4.最后获取Class类中的构造函数对象,通过构造函数创建实例对象*/public class ReflectDemo2 {@Testpublic void test01() throws IllegalAccessException, InstantiationException {//类中有无参构造方法Class clazz = Student.class;Object obj = clazz.newInstance();//默认调用的是无参的 - 创建实例System.out.println(clazz);//class Test25_Demo.TestDemo2.StudentSystem.out.println(obj);//Student{id=0, name='null'} - 当前的Object进行了向下转型给了反射获取到的类Student}@Testpublic void test02() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {//获取Class类中的构造函数对象Class clazz = Student.class;//获取到构造函数 - 有参Constructor constructor = clazz.getConstructor(int.class, String.class);//通过构造函数为属性赋值Object tom = constructor.newInstance(20, "Tom");//Student{id=20, name='Tom'}System.out.println(tom);}//演示普通的方式实例化对象做不到的事情@Testpublic void test03() {Student s = new Student();s.setId(1);//s.setName();//不能进行name的赋值,因为方法是私有的System.out.println(s);//Student{id=1, name='null'}}}
