前面我们对反射机制的理论知识进行了学习,现在我们来实际应用,从而更加了解它。首先我们先创建Person类,和Teacher类继承Person类(包含注解),供我们反射使用,具体如下:
package com.atguigu.javase.reflect; import java.io.Serializable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import org.junit.Test; @Retention(RetentionPolicy.RUNTIME) // 保持在运行时,才可以通过反射获取 @interface MyAnn { String name() default "张三"; int age() default 30; } // 创建Person类,为完成反射提供一个简单的类 class Person { public String gender; public int height; public double weight; private void privateTest() { System.out.println("Person.privateTest()"); } } // 创建Teacher类继承Person类 @MyAnn public class Teacher extends Person implements Serializable, Comparable { private static int counter = 100; public static void test() { System.out.println("static test()"); } public String name; private int age; private double salary; public Teacher() { } private Teacher(String name, int age, double salary) { super(); this.name = name; this.age = age; this.salary = salary; } public void eat(String something) { System.out.println("老师在吃" + something); } public void eat(String something, int time) { System.out.println("老师在吃" + something + "吃了" + time + "小时"); } @MyAnn(name="李四", age=40) private static final String concat(int i, double d, char c, boolean b) { return "" + i + d + c + b; } @Override public String toString() { return "Teacher [name=" + name + ", age=" + age + ", salary=" + salary + "]"; } @Override public int compareTo(Object o) { return 0; } }现在我们就可以测试反射创建对象、调用属性、方法等和正常情况创建有什么区别?
package com.atguigu.javase.reflect; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashSet; import java.util.Iterator; import java.util.Properties; import java.util.Set; import org.junit.Test; public class ReflectTest { // 正常方式创建对象,调用方法 @Test public void test1() { /* Teacher t1 = new Teacher(); // 由JVM自动 加载类, 再创建对象. t1.name = "小明"; t1.age = 20; t1.salary = 1000; System.out.println(t1.name); System.out.println(t1.age); System.out.println(t1.salary); t1.eat("回锅肉"); System.out.println(t1); */ } // 通过反射获取类的属性,以及私有属性的获取 @Test public void test2() { try { Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");// 根据类的全限定名称加载类并创建类模板对象, //加载类的过程就是由类加载器读取Teacher.class二进制文件,由类加载器生成Class对象 // 类模板对象中包含了类中的属性的定义(Field对象)和方法的代码(Method对象) Object object = clazz.newInstance(); // 对象的创建由方法来完成, 调用类的无参构造器创建对象 System.out.println(object); //((Teacher)object).name = "小红"; //Field ageField = clazz.getField("age"); // 只能获取公共的属性 Field ageField = clazz.getDeclaredField("age"); // 只在在本类中声明了的属性, 就可以获取到!!!, 不受访问控制修饰 ageField.setAccessible(true); ageField.set(object, 40);// 相当于object.age = 40; System.out.println(ageField.get(object)); // System.out.println(object.age); Field salaryField = clazz.getDeclaredField("salary"); System.out.println(salaryField); salaryField.setAccessible(true); // 突破封装,实现私有成员的访问 salaryField.set(object, 5000); System.out.println(salaryField.get(object)); Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true); // 突破封装,实现私有成员的访问 nameField.set(object, "小红"); System.out.println(object); } catch (ClassNotFoundException e) { // 类名不正确, 根据类名找到.class文件 e.printStackTrace(); } catch (InstantiationException e) { // 构造器调用错误!! e.printStackTrace(); } catch (IllegalAccessException e) { // 构造器封装 e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } } // 通过反射获取类实现了哪些接口 @Test public void test3() { try { Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher"); Class superClazz = clazz.getSuperclass(); System.out.println(superClazz); Class[] interfaceArr = clazz.getInterfaces(); for (int i = 0; i < interfaceArr.length; i++) { System.out.println("实现接口:" + interfaceArr[i]); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 创建对象的4种方法 @Test public void test4() { try { //1) 常规使用, 软编码 Class clazz1 = Class.forName("com.atguigu.javase.reflect.Teacher"); //2) 最简单, 硬编码 Class clazz2 = Teacher.class; System.out.println(clazz1 == clazz2); //3) 比较灵活, 硬编码 Class clazz3 = new Teacher().getClass(); System.out.println(clazz2 == clazz3); //4) 比较复杂, 先获取到类加载器对象,再手工加载类, 软编码 ClassLoader classLoader = this.getClass().getClassLoader(); Class clazz4 = classLoader.loadClass("com.atguigu.javase.reflect.Teacher"); System.out.println(clazz3 == clazz4); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 通过反射获取类加载器 @Test public void test5() { ClassLoader appClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(appClassLoader); ClassLoader extClassLoader = appClassLoader.getParent(); System.out.println(extClassLoader); ClassLoader bootstapClassLoader = extClassLoader.getParent(); System.out.println(bootstapClassLoader); System.out.println("" + Object.class.getClassLoader());// 引导类加载器加载核心类 System.out.println("" + Person.class.getClassLoader()); } @Test public void test6() throws IOException { // 通类加载器读取的资源文件的当前目录不是项目目录, 而是src目录 // src目录就是项目的classpath中的 // 可以直接从jar包中读取资源文件 //InputStream is = this.getClass().getClassLoader().getResourceAsStream("resource.properties"); InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/sun/corba/se/impl/logging/LogStrings.properties"); Properties properties = new Properties(); properties.load(is); System.out.println(properties.getProperty("IOR.nullPoa")); } // 通过反射获取类的方法,并实现方法 @Test public void test7() { try { Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher"); Object object = clazz.newInstance(); Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true); nameField.set(object, "小明"); System.out.println(object); // 调用方法 // 1) 从类模板对象中获取方法对象, getMethod会获取本类或者从父类继承的所有公共方式 Method eatMethod1 = clazz.getMethod("eat", String.class); // 2) 通过方法对象间接调用自己 Object retValue = eatMethod1.invoke(object, "肉包子"); // object.eat("肉包子"); System.out.println("方法返回值:" + retValue); Method eatMethod2 = clazz.getMethod("eat", String.class, int.class); eatMethod2.invoke(object, "紫菜包饭", 5); Method toStringMethod = clazz.getMethod("toString"); Object retValue2 = toStringMethod.invoke(object); System.out.println(retValue2); Method hashCodeMethod = clazz.getMethod("hashCode"); Object retValue3 = hashCodeMethod.invoke(object); System.out.println(retValue3); // 可以获取本类所有方法,包括私有方法 Method concatMethod = clazz.getDeclaredMethod("concat", int.class, double.class, char.class, boolean.class); concatMethod.setAccessible(true); Object retValue4 = concatMethod.invoke(object, 100, 3.14, '你', true); System.out.println(retValue4); System.out.println("修饰符:" + Modifier.toString(concatMethod.getModifiers())); Annotation annotation = concatMethod.getAnnotation(Test.class); // 获取注解 System.out.println(annotation); // getDeclaredMethod, 只能获取本类中声明的方法,从父类继承的无法拿到 //Method getClassMethod = clazz.getDeclaredMethod("getClass"); //System.out.println(getClassMethod); // 获取父类的私有方法,并通过子类对象来调用, 也是可以成功的, 说明子类继承父类的所有成员!! Method method = clazz.getSuperclass().getDeclaredMethod("privateTest"); method.setAccessible(true); method.invoke(object); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } // 通过反射获取构造器对象,从而完成对象的创建 @Test public void test8() { try { Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher"); // 使用其他构造器创建对象 // 1) 先获取到构造器对象 //Constructor constructor = clazz.getConstructor(String.class, int.class, double.class); Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class, double.class); int modifiers = constructor.getModifiers(); // 获取修饰符 Class[] typesClasses = constructor.getParameterTypes(); for (int i = 0; i < typesClasses.length; i++) { System.out.println("构造器参数:" + typesClasses[i]); } System.out.println(Modifier.toString(modifiers)); constructor.setAccessible(true); // 2) 间接调用构造器完成对象创建 Object object = constructor.newInstance("立超", 19, 10000); System.out.println(object); Constructor runtimeConstructor = Runtime.class.getDeclaredConstructor(); System.out.println(runtimeConstructor); runtimeConstructor.setAccessible(true); Object object2 = runtimeConstructor.newInstance(); System.out.println(object2); System.out.println(Runtime.getRuntime()); System.out.println(Object.class.getSuperclass()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } // 通过反射获取私有方法,注解 @Test public void test9() { try { Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher"); Annotation classannotation = clazz.getAnnotation(MyAnn.class); System.out.println(classannotation); // 可以获取本类所有方法,包括私有方法 Method concatMethod = clazz.getDeclaredMethod("concat", int.class, double.class, char.class, boolean.class); System.out.println("修饰符:" + Modifier.toString(concatMethod.getModifiers())); Annotation annotation = concatMethod.getAnnotation(MyAnn.class); // 获取注解 System.out.println(annotation); } catch (Exception e) { e.printStackTrace(); } } // 通过反射获取一个类的构造器,属性,方法 @Test public void test10() throws Exception { String className = "java.util.HashMap"; Class clazz = Class.forName(className); Constructor[] allConstructors = clazz.getDeclaredConstructors(); // 本类中声明的所有构造器 for (int i = 0; i < allConstructors.length; i++) { System.out.println(allConstructors[i]); } System.out.println("----------------------"); Field[] allFields = clazz.getDeclaredFields(); // 本类中声明的所有的属性 for (int i = 0; i < allFields.length; i++) { System.out.println(allFields[i]); } Field[] allPublicFields = clazz.getFields(); // 获取本类及从父类继承的所有公共属性 for (int i = 0; i < allPublicFields.length; i++) { System.out.println(allPublicFields[i]); } System.out.println("-----------------------------"); Method[] allMethods = clazz.getDeclaredMethods(); // 本类声明的所有方法 for (int i = 0; i < allMethods.length; i++) { System.out.println(allMethods[i]); } Method[] allPublicMethods = clazz.getMethods(); // 获取本类及从父类继承的所有公共方法 for (int i = 0; i < allPublicMethods.length; i++) { System.out.println(allPublicMethods[i]); } } // 写一个方法printClassDetails(String className) // 先打印类名和父类(getSuperClass())及实现的接口(getInterfaces()) // 在方法中打印类模板中的所有构造器,所有属性(包含从父类继承的公共属性), 所有方法(包含从父类继承的公共方法) 要求不要重复打印 // 打印的时候注意一下缩进 public void printClassDetails(String className) throws ClassNotFoundException { Class clazz = Class.forName(className); System.out.print("public class " + clazz.getSimpleName() + " extends " + clazz.getSuperclass().getSimpleName()); System.out.print(" implements "); Class[] allInterface = clazz.getInterfaces(); for (int i = 0; i < allInterface.length; i++) { System.out.print(allInterface[i].getSimpleName() + ","); } System.out.println("{"); System.out.println(); Set<Field> allFields = new HashSet<Field>(); for (Field field : clazz.getFields()) { allFields.add(field); } for (Field field : clazz.getDeclaredFields()) { allFields.add(field); } Iterator<Field> iterator = allFields.iterator(); while (iterator.hasNext()) { System.out.println("\t" + iterator.next()); } System.out.println(); for (Constructor constructor : clazz.getDeclaredConstructors()) { System.out.println("\t" + constructor); } System.out.println(); Set<Method> allMethods = new HashSet<Method>(); for (Method method : clazz.getMethods()) { allMethods.add(method); } for (Method method : clazz.getDeclaredMethods()) { allMethods.add(method); } System.out.println(); for (Method method : allMethods) { System.out.println("\t" + method); } System.out.println("}"); } // 调用printClassDetails方法 @Test public void exer1() { try { printClassDetails("java.io.ObjectOutputStream"); } catch (Exception e) { e.printStackTrace(); } } // 静态属性、静态方法的访问 @Test public void test11() { try { Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher"); //Object object = clazz.newInstance(); Field counterField = clazz.getDeclaredField("counter"); System.out.println(counterField); counterField.setAccessible(true); System.out.println(counterField.get(null)); // 静态属性的访问不需要对象, 所以传入null也可以 counterField.set(null, 10000); // 静态的设置也不需要对象 System.out.println(counterField.get(null)); // 静态属性的访问不需要对象, 所以传入null也可以 Method testMethod = clazz.getMethod("test"); testMethod.invoke(null); } catch (Exception e) { e.printStackTrace(); } } <span style="color:#ff0000;">// 反射在自定义泛型中的应用 // 通过反射获取子类的泛型类型->创建父类对象</span> @Test public void test12() throws InstantiationException, IllegalAccessException { Parent parent1 = new Child1(); Parent parent2 = new Child2(); } }
// 上面test12测试所需要的类,其中父类为自定义泛型类,子类确定泛型的类型,在父类无参构造器中通过反射获取到子类的泛型// 类型从而确定父类的泛型类型,然后创建对象,从而实现对象的创建 class Parent<T> { T t; Class clazz; public Parent() { Type type = this.getClass().getGenericSuperclass(); if (!(type instanceof ParameterizedType)) { // 在子类的声明中并没有任何的泛型信息 clazz = Object.class; } else { ParameterizedType parameteredType = (ParameterizedType)type; Type[] types = parameteredType.getActualTypeArguments(); clazz = (Class)types[0]; } System.out.println(clazz); try { t = (T) clazz.newInstance(); System.out.println(t); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } public T getT() { return t; } } class Child1 extends Parent<Person> { } class Child2 extends Parent { } class Child3 extends Parent<PrintStream> { }
// 反射可以应用在泛型类中,但是更加凸显出去其作用是在动态中