java之反射详解
反射概述
所谓反射,就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能就叫做java的反射机制。
反射的使用条件是必须先得到代表字节码的Class类。
当我们new一个类时,java就会加载这个类的.class文件,也就是jvm会在本地磁盘中查找.class文件,并加载到jvm的内存中,在这个过程的同时会产生一个Class对象。这个Class对象是jvm自动创建的,并且一个类只产生一个Class对象。
反射的本质就是得到Class对象后,反向获取类的各种信息。
如何获取Class对象
1.通过对象的.getClass()方法获取2.通过静态的class属性3.通过Class类的静态方法:forName(String className)具体代码如下:
·//通过getClass方法获得Class对象(都有UserInfo对象,再去获得其Class对象,画蛇添足,没有什么用) UserInfo userInfo = new UserInfo(); Class clz = userInfo.getClass(); //通过类的class属性 Class clz1 = UserInfo.class; //通过Class类的forName()方法,这种方式最常用 Class clz2 = Class.forName("suanfa.Reflction.UserInfo");
通过Class对象获得类和对象的属性和方法
本文使用的UserInfo对象的代码如下:
public class UserInfo implements User{ private int id; public String userName; private String password; public int getId(){ return id; } public void setId(int id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String toString(){ return "[ID: "+this.id+" name: "+this.userName+" password: "+this.password+"]"; } public String toString1(){ return "[ name: "+ this.userName+" password: "+this.password; } public UserInfo(){} public UserInfo(int id,String userName,String password){ this.password = password; this.userName = userName; this.id = id; } private UserInfo(int id,String password){ this.id = id; this.password = password; } @Override public void playGame() { System.out.println(gameName); } }
其中包含各种属性和方法。
下面,我们将通过Class类来得到它的构造方法:
//获取所有公有构造方法并打印 Constructor[] constructor = clz2.getConstructors(); for (Constructor constructor1 : constructor) { System.out.println(constructor1); } //获取所有的构造方法(包括:私有、受保护、默认、公有)并打印 Constructor[] clz2DeclaredConstructors = clz2.getDeclaredConstructors(); for (Constructor c : clz2DeclaredConstructors) { System.out.println(c); } //获取获取公有、无参的构造方法 final Constructor constructor1 = clz2.getConstructor(null); System.out.println(constructor1); //通过获取公有、无参构造方法实例该类 Object object = constructor1.newInstance(); UserInfo userInfo1 = (UserInfo) object; userInfo1.setId(2); userInfo1.setUserName("Yun"); userInfo1.setPassword("123456"); System.out.println(userInfo1);
对于多个参数的构造方法,在newInstance()中加上相应的参数即可。
通过Class类得到它的属性和方法:
//获取所有公有的字段并打印 Field[] fields = clz2.getFields(); for (Field field : fields){ System.out.println(field); } //获取所有的字段(包括私有、受保护、默认的)并打印 Field[] declaredFields = clz2.getDeclaredFields(); for (Field field:declaredFields){ System.out.println(field); } //获取特定的公有字段并调用(方法一) Field userName = clz2.getField("userName"); System.out.println(userName); Object o = clz2.getConstructor().newInstance(); userName.set(o,"xia"); UserInfo o1 = (UserInfo) o; System.out.println("验证姓名: "+o1.getUserName()); //获取特定的公有字段并调用(方法二) Method setUserName = clz2.getMethod("setUserName", String.class); setUserName.invoke(o,"Wan"); System.out.println("验证姓名: "+o1.getUserName()); System.out.println(); //获取私有字段并调用 Field password = clz2.getDeclaredField("password"); System.out.println(password); password.setAccessible(true); //暴力反射,解除私有限制 password.set(o,"121312"); System.out.println("验证密码: "+ o1.getPassword()); Method setPassword = clz2.getMethod("setPassword", String.class); setPassword.invoke(o,"131452"); System.out.println("验证密码: "+ o1.getPassword()); //获取所有的”公有“方法 Method[] methods = clz2.getMethods(); for (Method m : methods){ System.out.println(m); }
反射的一般流程是通过forName()方法获得Class类,在通过Class类得到它的属性和方法,并加以调用,从而达到无须new该类,便能使用该类。