大家好,欢迎来到IT知识分享网。
概念
1.反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。
2.反射可以在一个类运行的时候获取类的信息的机制,可以获取在编译期不可能获得的类的信息。
3.对于任意一个对象,都能调用它的任意一个方法和属性。
4.因为类的信息是保存在Class对象中的,而这个Class对象是在程序运行时被类加载器(ClassLoader)动态加载的。
5.当类加载器装载运行了类后,动态获取Class对象的信息以及动态操作Class对象的属性和方法的功能称为Java语音的反射机制。
作用:
1.反编译:.class —> .java。
2.通过反射机制访问Java对象中的属性、方法、构造方法等。
反射原理
Java反射的原理:java类的执行需要经历以下过程,
编译:.java文件编译后生成.class字节码文件
加载:类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang.Class对象实例
连接:细分三步
验证:格式(class文件规范) 语义(final类是否有子类) 操作
准备:静态变量赋初值和内存空间,final修饰的内存空间直接赋原值,此处不是用户指定的初值。
解析:符号引用转化为直接引用,分配地址
初始化:有父类先初始化父类,然后初始化自己;将static修饰代码执行一遍,如果是静态变量,则用用户指定值覆盖原有初值;如果是代码块,则执行一遍操作。
Java的反射就是利用上面第二步加载到jvm中的.class文件来进行操作的。.class文件中包含java类的所有信息,当你不知道某个类具体信息时,可以使用反射获取class,然后进行各种操作。
Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。
总结说:反射就是把java类中的各种成分映射成一个个的Java对象,并且可以进行操作。
获取class的三种方式
Class类主要方法
getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
newInstance():通过类的构造方法创建这个类的一个对象。
代码测试方法:
Person.java 类:
package reflect; import java.util.Date; /** * * * @author pine */ public class Person { private String username; private int age; private Date birthDay; public String nick; public Person(String username){ this.username = username; } public Person(){ } public Person(String username,int age){ this.username = username; this.age = age; } public String getNick() { return nick; } public void setNick(String nick) { this.nick = nick; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getBirthDay() { return birthDay; } public void setBirthDay(Date birthDay) { this.birthDay = birthDay; } private void sayHello(){ System.out.println("person sayHello ---"); } public void workIng(){ System.out.println("person work ing ---"); } @Override public String toString() { return "Person{" + "username='" + username + '\'' + ", age=" + age + ", birthDay=" + birthDay + ", nick='" + nick + '\'' + '}'; } }
ReflectTest.java类:
package reflect; import com.alibaba.fastjson.JSON; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * * 反射 * @author anzy */ public class ReflectTest { public static void main(String[] args) { // testClassEqual(); testMethodClass(); } public static void testClassEqual(){ //1、对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object // 类型的对象,而我不知道你具体是什么类,用这种方法 Person person = new Person(); Class c1 = person.getClass(); //2、通过类名.class 方式获取,此方法最为安全可靠,性能高 // 这说明任何一个类都有一个隐含的静态成员变量 class Class c2 = Person.class; //3、通过 Class 对象的 forName() 静态方法来获取,用的最多, // 但可能抛出 ClassNotFoundException 异常 Class c3 = null; try { c3 = Class.forName("reflect.Person"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(c1.equals(c2)); System.out.println(c1.equals(c3)); System.out.println(c3.equals(c2)); } public static void testMethodClass(){ Class c3 = null; try { c3 = Class.forName("reflect.Person"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println("c3.getName():" + c3.getName()); // 获得类的public类型的属性。 Field[] fields = c3.getFields(); System.out.println("c3.getFields():" + JSON.toJSON(fields)); //输出结果:c3.getFields():[{"accessible":false,"declaredAnnotations":[],"synthetic":false,"annotatedType": // {"declaredAnnotations":[],"annotations":[],"type":"java.lang.String"}, // "enumConstant":false,"name":"nick","annotations":[],"genericType":"java.lang.String", // "modifiers":1,"type":"java.lang.String","declaringClass":"reflect.Person"}] // 从输出结果可以看到,只拿到了Person类中的nick public属性。 Field[] fieldsAll = c3.getDeclaredFields(); System.out.println("c3.getDeclaredFields():" + JSON.toJSON(fieldsAll)); try { // 只能获取public方法,获取private会报错:java.lang.NoSuchMethodException: reflect.Person.sayHello() Method method = c3.getMethod("workIng",null); System.out.println("method: " + method); Method[] methods = c3.getMethods(); System.out.println("methods: " + methods); // public,private 方法都能获取 Method declaredMethod = c3.getDeclaredMethod("sayHello",null); System.out.println("declaredMethod: " + declaredMethod); Method[] declaredMethods = c3.getDeclaredMethods(); System.out.println("declaredMethods: " + declaredMethods); // 获取构造函数 Constructor<Person> constructors[] = c3.getConstructors(); System.out.println("constructors: " + constructors); // JSON.toJSON(constructors) 会报错,栈溢出 Exception in thread "main" java.lang.StackOverflowError // System.out.println("constructors: " + JSON.toJSON(constructors)); // 通过类的构造方法创建这个类的一个对象。 Person person = constructors[0].newInstance("pine",1); System.out.println("person: " + person); } catch (NoSuchMethodException e) { e.printStackTrace(); }catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }
c3.getMethod()拿到的结果:
c3.getDeclaredMethods() 拿到的结果
两个对比可以发现:
getMethods() 能够获取Object类中的public方法。
getDeclaredMethods()获取不到。
让我们引发思考想到了,普通类与Object的关系:
Object类是一切java类的父类,对于普通的java类,即便不声明,也是默认继承了Object类。典型的,可以使用Object类中的toString()方法。
Class能实现的功能
1判断对象属于哪个类
Person person = new Person();
Class class2= person.getClass();
System.out.println(“class2:”+class2);
输出:class2:class reflect.Person
2获取类信息
Class class1 = Person.class;
Method[] methods = class1.getMethods();
Method[] declaredMethods = class1.getDeclaredMethods();
Field[] declaredFields = class1.getDeclaredFields();
3构建对象
Person person = new Person();
Class class2= person.getClass();
Object o = class2.newInstance();
//强转前先用instanceof判断
if(o instanceof Person){
((Person) o).workIng();
}
4动态执行方法
Class class1 = Class.forName(“reflect.Person”);
Method work = class1.getDeclaredMethod(“work”);
Person person = new Person();
work.invoke(person);
5动态操作属性
Class class1 = Class.forName(“reflect.Person”);
Person person = new Person();
Field field = class1.getDeclaredField(“username”);
field.set(person,”pine”);
6动态代理
其他:
分享一下与内容有关的思维导图与流程图
反射思维导图:https://www.processon.com/view/link/5e1eb718e4b0169fb52123db
类加载流程图:https://www.processon.com/view/link/5e1eb5f6e4b04e6f9a
希望能对大家有帮助,有问题的地方希望大家指正。
能够点个赞转发,关注一下就更好了。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/59298.html