类中类
1. 反射介绍
反射这一概念最早由编程开发人员Smith在1982年提出,主要指应用程序访问、检测、修改自身状态与行为的能力。这一概念的提出立刻吸引了编程界的极大关注,各种研究工作随之展开,随之而来引发编程革命,出现了多种支持反射机制的面向对象语言。
在计算机科学领域,反射是指一类能够自我描述和自控制的应用。在Java编程语言中,反射是一种强有力的工具,是面向抽象编程一种实现方式,它能使代码语句更加灵活,极大提高代码的运行时装配能力。
2. 反射在java中的体现
Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。案例:
和https://programmer.help/blogs/reflection-and-dynamic-agent-in-mybatis.html
意味着搞懂了反射,也就搞明白了大部分框架,且务必搞明白:是技术难还是纷繁琐杂还是功能模块多导致工作量大,性质是不一样的
直觉告诉我,技术难占比很小,5~10%的比例就已经很不错了,是繁琐和模块多工作量的问题,几十上百上千的模块
2.1 获取Class对象
反射其实是获取类的字节码文件(在JVM的世界里只会有有一份,不管以不同的方式加载多少次),也就是.class文件,那么我们就可以通过Class这个对象进行获取,有三种方式:通过类名的class属性、对象的getClass()方法和java.lang.Class的静态方法forName(“类全路径”)
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
*
* @author dgm
* @describe "java 反射测试"
* @date 2020年5月11日
*/
public class ReflectionClassTest {
public static void main(String[] args) {
//获取Class对象(三种方式)
Class<?> ChildClassFirst = ChildClass.class;
Class<?> ChildClassSecond = new ChildClass(1).getClass();
Class<?> ChildClassThird = null;
try {
// below method is used most of the times in frameworks like JUnit
//Spring dependency injection, Tomcat web container
//Eclipse auto completion of method names, hibernate, Struts2 etc.
//because ChildClass is not available at compile time
ChildClassThird = Class.forName("code.reflection.ChildClass");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("first: "+ ChildClassFirst.getCanonicalName());
System.out.println("second: "+ ChildClassSecond.getCanonicalName());
System.out.println("third: "+ ChildClassThird.getCanonicalName());
System.out.println(ChildClassFirst==ChildClassSecond);
System.out.println(ChildClassFirst==ChildClassThird);
System.out.println(ChildClassSecond==ChildClassThird);
}
}
输出效果:
2.2 获取类所有的公共public构造器
可用getConstructors()返回类的所有公共构造器
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
*
* @author dgm
* @describe "java 公共构造器测试"
* @date 2020年5月11日
*/
public class ReflectionConstructorTest {
public static void main(String[] args) {
// 获取Class对象(用的是java.lang.Class.forName())
Class<?> ChildClass = null;
// 获取所有公共构造器
Constructor<?>[] publicConstructors = null;
try {
ChildClass = Class.forName("code.reflection.ChildClass");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 已经确定能Class对象,实际情况需要做判断类加载是否成功
publicConstructors = ChildClass.getConstructors();
System.out.println("公共构造器个数:" + publicConstructors.length);
for (Constructor constructor : publicConstructors) {
System.out.println("构造器:" + constructor);
}
}
}
输出效果:
源文件的构造器:
2.3 获取类所有的公共public field属性
可用
getFields()返回类的所有公共属性(包括从父类和接口继承过来的)
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
*
* @author dgm
* @describe "java 公共field属性测试"
* @date 2020年5月11日
*/
public class ReflectionFieldTest {
public static void main(String[] args) {
// 获取Class对象(用的是java.lang.Class.forName())
Class<?> Ch