反射
一、什么是反射
java程序在运行期间能够动态加载、解析、使用一些在编译阶段并不确定的数据类型
二、反射的功能
2.1、加载运行时才能确定的数据类型
2.2、解析类的结构,获取内部信息
2.3、操作该类型或其实例:访问属性、调用方法、创建新对象
package com.study.test; import static java.lang.System.out; class aaa { void test() { out.println("您好!"); } } public class ClassLoaderJZ { public static void main(String[] args) throws Exception { // 反射的概览 // 传统的实现test方法的调用通过如下方式 aaa a1 = new aaa(); a1.test(); // 通过反射来实现test方法的调用 aaa.class.newInstance().test();// 获取类模板调用方法实例化对象,最后调用test方法,更加简洁 // 返回默认的无参构造函数 返回类型为数组 out.println(aaa.class.getDeclaredConstructors()[0]); out.println(aaa.class.getSuperclass());// 返回aaa的父类Object // 输出为空可知Object已经是最高的父类了,不能再回溯了 out.println(aaa.class.getSuperclass().getSuperclass()); } }
三、获取Class对象的方法
3.1、Class的静态函数forName()获取
3.2、调用从Object继承下来的getClass()函数
3.3、通过.class表达式获取
package com.study.test; import static java.lang.System.out; class aaa { void test() { out.println("您好!"); } } public class ClassLoaderJZ { public static void main(String[] args) throws Exception { // 获取Class对象的途径 // 针对引用数据类型 //1、Class的静态函数forName()获取 Class<?> c1 = Class.forName("com.study.test.aaa"); out.println(c1); // 2、调用从Object继承下来的getClass()函数 aaa a1 = new aaa(); Class<?> c2 = a1.getClass(); out.println(c2); // 3、通过.class表达式获取 out.println(aaa.class); Class<aaa> c3 = aaa.class; out.println(c3); // 针对基本数据类型及void // 通过TYPE属性得到包装类的基本类型 int i = 1;// 栈区存储 基本类型 Integer j = new Integer(1);// 堆区存储 包装类 等于Integer j=1; Class<Integer> c4 = Integer.TYPE;// 输出int 返回包装类的基本类型 out.println(c4); // 使用.class 表达式 Class c5 = int.class; Class c6 = double.class; Class c7 = void.class; out.println(c5); out.println(c6); out.println(c7); } }
四、反射操作构造函数
4.1 调用无参、有一个参数、有多个参数的构造函数实例化对象
package com.study.test; import static java.lang.System.out; import java.lang.reflect.Constructor; class aaa { aaa() { out.println("aaa()"); } aaa(int i) { out.println("aaa(int i)"); } aaa(int i, String j) { out.println("aaa(int i,String j)"); } void test() { out.println("void test()"); } } public class ClassLoaderJZ { public static void main(String[] args) throws Exception { // 通过反射我们获得了构造函数的规则 我们获得的是构造函数的数组 out.println(aaa.class.getDeclaredConstructors().length); // out.println(aaa.class.getDeclaredConstructors()[0].newInstance()); // out.println(aaa.class.getDeclaredConstructors()[1].newInstance(1)); // 遍历输出构造函数 默认按参数个数的多少由大到小一次输出 for (Constructor<?> c1 : (aaa.class.getDeclaredConstructors())) { out.println(c1); } // 怎样通过反射实例化调用函数? // aaa.class.newInstance().test(new int[]{4,5,6}); // 错的aaa.class.getDeclaredConstructors()[0].newInstance(1); // //传统方案调用test // aaa a1=new aaa(); // a1.test(new int[]{1,2,3}); // 调用无参的构造函数动态生成实例 // aaa.class.newInstance().test(); aaa.class.getDeclaredConstructors()[2].newInstance(); // 调用带一个参数构造函数生成实例 aaa.class.getDeclaredConstructors()[1].newInstance(1); // 调用带两个参数构造函数生成实例 aaa.class.getDeclaredConstructors()[0].newInstance(1, "abc"); } }
输出结果:
3
com.study.test.aaa(int,java.lang.String)
com.study.test.aaa(int)
com.study.test.aaa()
aaa()
aaa(int i)
aaa(int i,String j)
4.2 获取构造函数的修饰符、名字、以及参数
package com.study.test; import static java.lang.System.out; import java.lang.reflect.Constructor; class aaa { aaa() { out.println("aaa()"); } aaa(int i) { out.println("aaa(int i)"); } aaa(int i, String j) { out.println("aaa(int i,String j)"); } void test() { out.println("void test()"); } } public class ClassLoaderJZ { public static void main(String[] args) throws Exception { // 通过反射我们获得了构造函数的规则 我们获得的是构造函数的数组 out.println(aaa.class.getDeclaredConstructors().length); // out.println(aaa.class.getDeclaredConstructors()[0].newInstance()); // out.println(aaa.class.getDeclaredConstructors()[1].newInstance(1)); // 遍历输出构造函数 默认按参数个数的多少由大到小一次输出 // getConstructors()函数获取public的构造函数;getDeclaredConstructors()获取所有的构造函数 for (Constructor<?> c1 : (aaa.class.getDeclaredConstructors())) { // 获取构造函数的修饰符、名字、参数类型 out.println("获取构造函数的修饰符、名字、参数类型"); out.println(c1.getModifiers()); out.println(c1.getName()); for (Class c2 : c1.getParameterTypes()) { out.println(c2); } } } }
输出结果:
3
获取构造函数的修饰符、名字、参数类型
0
com.study.test.aaa
int
class java.lang.String
获取构造函数的修饰符、名字、参数类型
0
com.study.test.aaa
int
获取构造函数的修饰符、名字、参数类型
0
com.study.test.aaa
五、反射获取接口.
package com.study.test; import static java.lang.System.out; interface I1 { } interface I2 { } class aaa implements I1, I2 { public aaa() { out.println("aaa()"); } private aaa(int i) { out.println("aaa(int i)"); } protected aaa(int i, String j) { out.println("aaa(int i,String j)"); } void test() { out.println("void test()"); } } public class ClassLoaderJZ { public static void main(String[] args) throws Exception { // 获取接口 out.println("获取接口"); for (Class<?> c2 : aaa.class.getInterfaces()) { out.println(c2); } } }
输出结果:
获取接口
interface com.study.test.I1
interface com.study.test.I2
六、反射获取方法的返回类型,修饰符,参数类型等等
package com.study.test; import static java.lang.System.out; import java.lang.reflect.Method; interface I1 { } interface I2 { } class aaa implements I1, I2 { public aaa() { out.println("aaa()"); } private aaa(int i) { out.println("aaa(int i)"); } protected aaa(int i, String j) { out.println("aaa(int i,String j)"); } void test() throws Exception { out.println("void test()"); } void test1() { out.println("void test1()"); } void test2() { out.println("void test2()"); } } public class ClassLoaderJZ { public static void main(String[] args) throws Exception { // getMethod()方法获得所有public的方法包括从Object继承的方法 // for(Method m:aaa.class.getMethods()){ // out.println(m); // }; // getDeclaredMethods()方法获得所有在本类中自己声明的方法 for (Method m : aaa.class.getDeclaredMethods()) { out.println("输出方法的返回类型,参数类型,修饰符,以及方法的异常类型"); out.println(m.getReturnType()); out.println(m.getParameters().length); out.println(m.getModifiers()); for (Class c : m.getExceptionTypes()) { out.println(m); } } } }
输出结果:
输出方法的返回类型,参数类型,修饰符,以及方法的异常类型
void
0
0
void com.study.test.aaa.test() throws java.lang.Exception
输出方法的返回类型,参数类型,修饰符,以及方法的异常类型
void
0
0
输出方法的返回类型,参数类型,修饰符,以及方法的异常类型
void
0
0
七、通过反射调用方法
package com.study.test; import static java.lang.System.*; import java.lang.reflect.Constructor; import java.lang.reflect.Method; interface I1 { } interface I2 { } class aaa implements I1, I2 { public aaa() { out.println("aaa()"); } public aaa(int i) { out.println("aaa(int i)"); } protected aaa(int i, int j) { out.println("aaa(int i,String j)"); } public void test() { out.println("void test()"); } public void test1(int i) { out.println("void test1()"); } void test2(int j, int k) { out.println("void test2()"); } } public class ClassLoaderJZ { public static void main(String[] args) throws Exception { // getMethod()方法获得所有public的方法包括从Object继承的方法 // for(Method m:aaa.class.getMethods()){ // out.println(m); // }; // getDeclaredMethods()方法获得所有在本类中自己声明的方法 out.println("获得所有在本类中自己声明的方法"); for (Method m : aaa.class.getDeclaredMethods()) { out.println(m); } // 注意:遍历出的构造函数是无序的 out.println("构造函数"); for (Constructor c : aaa.class.getDeclaredConstructors()) { out.println(c); } out.println("方法调用"); aaa.class.getDeclaredMethods()[0].invoke(aaa.class.getDeclaredConstructors()[2].newInstance(), null); aaa.class.getDeclaredMethods()[1].invoke(aaa.class.getDeclaredConstructors()[1].newInstance(1), 1); } }
输出结果:
获得所有在本类中自己声明的方法
public void com.study.test.aaa.test()
public void com.study.test.aaa.test1(int)
void com.study.test.aaa.test2(int,int)
构造函数
protected com.study.test.aaa(int,int)
public com.study.test.aaa(int)
public com.study.test.aaa()
方法调用
aaa()
void test()
aaa(int i)
void test1()
八、反射得到所有的字段
package com.study.test; import static java.lang.System.out; import java.io.IOException; import java.lang.reflect.Field; class aa { private int j = 2; public static int i = 1; void test1(int i) throws Exception, IOException { out.println("test"); } public static int test2() { out.println("test1"); return 1; } } public class ClassLoaderJZ { public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException { // 得到第一个字段内容 Field f1 = aa.class.getDeclaredField("j"); f1.setAccessible(true); out.println(f1.get(aa.class.newInstance())); // 得到第二个字段内容 out.println(aa.class.getDeclaredField("i").get(null)); } }
输出结果:
2
1