java中不通过new关键字获取对象并且使用类对象中的成员变量和方法,第一时间我们会想到可以使用反射去实现这些功能,反射很强大,学会了我们可以搭配很多东西一起使用,下面我们一起来学习使用反射吧!
我们使用一个Book类来实现一下反射
代码如下:
public class Book { private Integer id; private String name; public Integer age; public Book() { System.out.println("Public 无参构造函数"); } public Book(String name) { System.out.println("Public 带参构造函数"); } private Book(String name,Double price){ System.out.println("Private 带两参构造函数"); } public void printAll(){ System.out.println("公开方法"); } private void printOne(){ System.out.println("私有方法"); } }
获取类的三种方式
第一种:使用Class.forName(String classPath) //ClassPath:写需要反射的类名,一般是以包名.类名
注意事项:这里会产生一个ClassNotFoundException异常,我们需要将异常处理或者抛出
返回值:Class对象
try {
Class clz = Class.forName("com.entity.Book");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
第二种:直接使用Class clz = 类名.class
这种情况一般在我们知道有这个类的时候去使用
Class clz = Book.class;
第三种:Class clz = 对象. getClass();
前提是对象已经被实例化出来了
Book book = new Book(); Class clz = book.getClass();
总结:这三种方法都有各自的优点,一般我们使用第一种比较多,按照自己的实际需求去使用才是最好的
获取构造函数
getDeclaredConstructors(); 获取所有的构造函数
getDeclaredConstructor(参数类型); 获取一个所有的构造函数
getConstructors(); 获取所有公开的构造函数
getConstructor(参数类型); 获取单个公开的构造函数
使用方法:
//获取所有的构造函数 Constructor[] constructors = clz.getDeclaredConstructors(); //获取单个所有的构造函数 try { Constructor constructor = clz.getDeclaredConstructor(String.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } //获取所有的公开构造函数 Constructor[] constructors1 = clz.getConstructors(); //获取单个公开构造函数 try { Constructor constructor = clz.getConstructor(String.class); } catch (NoSuchMethodException e) { e.printStackTrace(); }
获取修饰符
getModifiers(); //获取所有修饰符
返回类型:整数类型,如果有两个修饰符,则返回两个修饰符之和,例如public static void getAll(){ }
返回值会是public和static之和
整数定义:
0--默认不写 1--public 2--private 4--protected
8--static 16--final 32--synchronized
64--volatile 128--transient 256--native
512--interface 1024--abstract
for (Constructor constructor : constructors) { System.out.println(constructor.getModifiers()); }
Modifier.isStatic(clz.getModifiers) //判断是否是static类型
Modifier中还有一些判断其它的方法,都是以is开头
获取名字
返回类型:String,可以反射类名,方法名,构造函数名等等
getName(); //获取全名 例如:com.bean.Book
getSimpleName() //获取类名 例如:Book
Class clz = Book.class; String name1 = clz.getName(); String name2 = clz.getSimpleName();
获取包
返回类型:package
getPackage();
Package aPackage = clz.getPackage();
获取接口
返回类型:Class[] interfaces
getInterfaces()
Class[] interfaces = clz.getInterfaces();
获取父类/超类
返回类型:Class superclass
getSuperclass()
Class superclass = clz.getSuperclass();
获取方法
getMethods() //获取所有公开的方法
注意:它会将系统自带的方法也得到
Class clz = Class.forName("Book"); Method[] methods = clz.getMethods(); //获取所有的公开方法 for (Method method : methods) { System.out.println(method.getName()); }
getMethod(String name) //获取单个公开的方法,参数是可以指定方法名
Method method = clz.getMethod("printAll"); //获取单个的公开方法 method.invoke(clz.newInstance(),null);
getDeclaredMethods() //获取所有的方法
注意:它不会获取系统自带的方法
Method[] methods1 = clz.getDeclaredMethods(); //获取所有方法 for (Method method1 : methods1) { System.out.println(method1.getName()); }
getDeclaredMethod(String name) //获取单个的所有方法 参数是可指定方法名
Method method1 = clz.getDeclaredMethod("printOne"); //获取单个所有的方法 System.out.println(method1.getName());
获取字段
公开(Public)
getFields() //获取所有的公开字段
getField(String name) //参数可以指定字段 获取单个public字段
所有
getDeclaredFields() //获取所有的字段
getDeclaredField(String name) //获取单个字段 参数可以指定字段
Class clz = Book.class; //Public Field[] fields = clz.getFields(); //所有公开字段 Field id = clz.getField("age"); //age字段 //所有 Field[] declaredFields = clz.getDeclaredFields(); //所有字段 clz.getDeclaredField("name"); //name字段
实例化对象
newInstance(Object initargs)
第一种方式
Class clz = Book.class; Object obj = clz.newInstance(); //将创建一个无参book对象
第二种方式
Class clz = Book.class; Constructor constructor = clz.getDeclaredConstructor(); //获得无参构造 Object obj = constructor.newInstance(); //实例化book对象
设置访问属性
clz.setAccessible(true) //可访问
clz.setAccessible(false) //不可访问
//默认是false
Field id = clz.getField("age"); //age字段 id.setAccessible(true); //设为可访问 id.setAccessible(false); //设为不可访问
使用方法
method.invoke(Object obj,Object... args)
obj:如果是实例方法,则放个该方法的类对象给它
obj:静态方法,写null
args:方法的参数值,没有写null,或不写都行
Method method = clz.getMethod("printAll"); //获取单个的公开方法 method.invoke(clz.newInstance(),null); //使用方法
当然,这些都只是常用的,反射不仅仅是只有这些