最近又要面试新人,因此翻了翻之前的代码,忽然发现了一个有意思的问题。java
问:以下一个Student类,请实例Student并对其成员变量赋值。面试
public class Student { private String NAME; private int AGE; @Override public String toString() { return "Student [name=" + NAME + ", age=" + AGE + "]"; } }
若是是个入行没多久或者基础不太好的初学者来看,确定一脸蒙逼。两个私有成员变量set,get方法也没有,有参构造器也不提供,怎么搞?ide
其实也不难,首先看到这种只提供私有成员变量第一个想到的确定是反射。代码以下:测试
public static void main(String[] args) throws Exception { Class clazz = Student.class; Object obj = clazz.newInstance(); Field fieldName = clazz.getDeclaredField("name"); Field fieldAge = clazz.getDeclaredField("age"); fieldName.setAccessible(true); fieldAge.setAccessible(true); fieldName.set(obj, "二十岁之后"); fieldAge.set(obj,21); System.out.println(obj); }
那么什么是反射呢?spa
JAVA反射机制是在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。 code
1.类的加载概述对象
当程序要使用某个类时,若是该类还未被加载到内存中,则系统会经过加载,链接,初始化三步来实现对这个类进行初始化。继承
(1)加载 接口
就是指将class文件读入内存,并为之建立一个Class对象。内存
任何类被使用时系统都会创建一个Class对象。
(2)链接
1>验证 : 是否有正确的内部结构,并和其余类协调一致
2>准备 : 负责为类的静态成员分配内存,并设置默认初始化值
3>解析: 把类中的符号引用转换为直接引用
(3)初始化 就是类的初始化步骤
2.类的加载时机
(1)建立类的实例
访问类的静态变量,或者为静态变量赋值
(2)调用类的静态方法
使用反射方式来强制建立某个类或接口对应的java.lang.Class对象
(3)初始化某个类的子类
直接使用java.exe命令来运行某个主类
3.类加载器的概述
负责将.class文件加载到内在中,并为之生成对应的Class对象。
4.类加载器的分类
Bootstrap ClassLoader 根类加载器
Extension ClassLoader 扩展类加载器
Sysetm ClassLoader 系统类加载器
5.类加载器的做用
(1)Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
好比System,String等。在JDK中JRE的lib目录下rt.jar文件中
(2)Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
(3)Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
/** * 反射: 就是发生在运行状态下一种机制. 对于任意一个类咱们能够获取到该类的字节码文件 对象 , 获取到 * 字节码文件对象之后,咱们就能够剖析找个类 * java为咱们的类中的每一种成员提供了对应的类对其进行描述: * * 成员变量 Field * 构造方法 Constructor * 成员方法 Method * * 获取一个类对应的字节码文件对象: * * (1): 经过调用getClass方法获取该类对应的字节码文件对象 * (2): 经过静态的class属性获取 * (3): 咱们能够经过Class类中的一个静态方法叫作: forName(String className): * public static Class<?> forName(String className) * */ |
代码示例以下:经过三种方式去得的到Person类对应的字节码文件对象,如下输出结果都为True
/** * 获取构造方法的方法
//获取全部公共的构造方法 * public Constructor<?>[] getConstructors()
// 获取全部的构造方法,包括私有的 * public Constructor<?>[] getDeclaredConstructors()
//获取带指定参数的共有构造方法 * public Constructor<T> getConstructor(Class... parameterTypes) * public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) */
代码示例为获取Student类的全部构造方法:
Student类:
测试代码,获取Student类的三个构造方法
输出为
测试代码,获取Student类参数为两个的公有构造器,并实例化对象
结果为:
经过反射得到类中的成员变量并使用
一共四个方法能够获取
getField(String name):获取单个成员变量,指定的成员变量对应的名称
getFields():获取的是全部公共的成员变量,包含从父类中继承过来的
getDeclaredFields():获取的是本类中全部的成员变量,包含私有的
getDeclaredField(String name):获取本类中指定成员变量
其中Student成员变量都为private且不提供Set、Get方法,且不经过两个参数的构造器实例化对象