引言:
当我们需要对不明确的对象操作时,为了能准确操作对象,正常需要对其不断缩小范围确定其类型。即使如此,涉及到
封装性仍然无可奈何。 这时在程序运行时,存放的一个class文件像一面镜子反射出此类对象的完整信息,为我们提供便捷。由此反射,泛型,动态代理等,体现java动态的特性。
一,Class类
每一个类都有一个 Class 对象,每当编译一个新类就产生一个 Class 对象,基本类型 (boolean, byte, char, short, int, long, float, double)有 Class 对象,就连关键字 void 也有 Class 对象(void.class)。Class 对象对应着 java.lang.Class 类,如果说类是对象的抽象和集合,那么 Class 类就是对类的抽象和集合。
每个通过关键字 class 标识的类,在内存中有且只有一个与之对应的 Class 对象来描述其类型信息,不论通过哪种方式获得该类的 Class 对象,它们返回的都是指向同一个 java 堆地址上的 Class 引用,jvm 不会创建两个相同类型的 Class。也就是说,无论创建多少个实例对象,其依据的都是同一个 Class 对象。java 虚拟机中使用双亲委派模型来组织类加载器之间的关系,来保证 Class 对象的唯一性。
这也是万物皆对象的重要体现。这是动态代理的基础,也是框架设计的灵魂。
/*
* Private constructor. Only the Java Virtual Machine creates Class objects.
* This constructor is not used and prevents the default constructor being
* generated.
*/
private Class(ClassLoader loader) {
// Initialize final field for classLoader. The initialization value of non-null
// prevents future JIT optimizations from assuming this final field is null.
classLoader = loader;
}
二,ClassLoader抽象类
Java类加载器(Class Loader)是Java虚拟机(JVM)的一部分,负责将类的字节码加载到内存中,并将其转换为可执行的Java对象。类加载器在Java应用程序中起着重要的作用,它实现了动态加载类的机制,使得Java具备了灵活性和可扩展性。
ClassLoader是Java的核心组件,所有的Class都是由ClassLoader进行加载的,ClassLoader负责通过各种方式将Class信息的二进制数据流读入JVM内部,转换为一个与目标类对应的java.lang.Class对象实例。然后交给Java虚拟机进行链接、初始化等操作。
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
三,Constructor类
构造器通常也叫构造方法,构造函数,构造器在每个项目中几乎无处不在。当你new一个对象时,就会调用构造器。一般用来初始化成员属性和成员方法,即new对象产生后,就调用了对象了属性和方法。
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Object o = constructor.newInstance();
四,Field类
java.lang.reflect.Field 为我们提供了获取当前对象的成员变量的类型,和重新设值的方法。
权限
- 访问权限控制符:`public`, `protected`, `private`
- 限制只能有一个实例的:`static`
- 不允许修改的:`final`
- 不会被序列化:`transient`
- 线程共享数据的一致性:`volatile`
基本类型( 8 种)
- 整数:byte, short, int, long
- 浮点数:float, double
- 字符:char
- 布尔值:boolean
引用类型
- 所有的引用类型都继承自 java.lang.Object
- 类,枚举,数组,接口都是引用类型
- java.io.Serializable 接口
五,Method类
代表类中的一个方法的定义,一个Method由修饰符,返回值,方法名称,参数列表组合而成
Method提供的方法
- getName();获得方法名。
- getModifiers();获得修饰符。
- getReturnTypes();返回值类型。返回class
- getParameterTypes();返回Class[],参数类型的数组。
- invoke(Object obj,Object..args);
获得Method
- Method GetMethod(String name,Class<?>...args);
- Method[] getMethod();获得所有的公共方法。
- Method[] getMethod();获得所有的公共方法。
- Method[] getDeclaredMethods();获得当前类中定义的所有方法。
六,Modifier类
在查看反射相关的Class、Field 、Constructor等类时,看到他们都有这样一个方法getModifiers()返回此类或接口以整数编码的 Java 语言修饰符。如需要知道返回的值所代表的意思,则需要用到java.lang.reflect.Modifier 这个类,这个类提供了 static 方法和常量,可以对类和成员访问修饰符进行解码。
访问修饰符列表
public:Modifier.PUBLIC (0x00000001) (1)
private:Modifier.PRIVATE (0x00000002) (2)
protected:Modifier.PROTECTED (0x00000004) (4)
static:Modifier.STATIC (0x00000008) (8)
final:Modifier.FINAL (0x00000010) (16)
synchronized:Modifier.SYNCHRONIZED(0x00000020) (32)
volatile:Modifier.VOLATILE(0x00000040) (64)
transient:Modifier.TRANSIENT(0x00000080) (128)
native:Modifier.NATIVE(0x00000100) (256)
interface:Modifier.INTERFACE(0x00000200) (512)
abstract:Modifier.ABSTRACT(0x00000400) (1024)
strict:Modifier.STRICT(0x00000800) (2048)
七,总结
Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。