一、什么是类对象
类的对象:基于某个类new出来的对象,也称为实例对象。
类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)。
注:每个类加载到内存都会生成一个唯一的类对象。
二、获取类对象的方法
2.1 通过类的对象,获取类对象
Person p = new Pserson();
Class c = p.getclass();
2.2 通过类名获取类对象
Class c = 类名.class;
2.3 通过静态方法获取类对象(任何类型都有.class)
Class c = Class.forName("包名.类名");
2.4 ReflectUtil
Hutool工具包中工具类
2.5 示例
未使用工具类进行反射:
/**
* 获取实体类字段的description
*
* @param clazz
* @return
*/
private static Map<String, String> getFieldSwaggerValue(Class clazz) {
Field[] fields = clazz.getDeclaredFields();
Map<String, String> map = new HashMap<>();
for (Field f : fields) {
boolean annotationPresent2 = f.isAnnotationPresent(ApiModelProperty.class);
if (annotationPresent2) {
ApiModelProperty name = f.getAnnotation(ApiModelProperty.class);
String nameStr = name.value();
map.put(f.getName(), nameStr);
}
}
return map;
}
ReflectUtil 工具类进行反射:
Map<String, Field> xssoAccount = ReflectUtil.getFieldMap(XssoAccount.class);
三、反射机制
1、反射机制有什么用?
通过java语言中的反射机制可以操作字节码文件,可以读和修改字节码文件,通过反射机制可以操作代码片段(class文件)。
2、反射机制的相关类在哪个包下?
java.lang.reflect.*
3、反射机制相关的类有哪些?
java.lang.Class 代表字节码文件
java.lang.reflect.Method 代表字节码中的方法字节码
java.lang.reflect.Constructor 代表字节码中的构造方法的字节码
java.lang.reflect.Field 代表字节码中的属性字节码
4、通过反射实例化对象
Class c = Class.forName("包.User"); //c代表User类型
Object obj = c.newInstance(); //newInstance()这个方法会调用User这个类的无参构造方法,完成对象的创建
优点:使程序更加灵活,代码不需要改动,可以修改配置文件,配置文件修改之后,可以创建出不同的实例对象。
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
// 通过IO流读取。properties文件(具有局限性,只能在idea中)
FileReader reader = new FileReader("./src/classinfo.properties");
// 创建属性类对象
Properties pro=new Properties();
// 加载
pro.load(reader);
// 关闭流
reader.close();
// 通过key获取value
String className = pro.getProperty("className");
// 通过反射机制实例化对象
Class c = Class.forName(className);
Object obj = c.newInstance();
System.out.println(obj);
}
5、 以流的形式直接返回
public static void main(String[] args) throws IOException {
// 获取一个文件的绝对路径
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("classinfo.properties");
Properties pro = new Properties();
pro.load(is);
is.close();
// 通过key获取value
String className = pro.getProperty("className");
System.out.println(className);
}
6、资源绑定器
public static void main(String[] args) {
// java.util包下提供了一个资源绑定器,便于获取配置文件中的内容
// 属性配置文件xxx.properties必须放在类路径下(src)
// 资源绑定器,只绑定xxx.properties文件,并且这个文件必须在类路径下,文件扩展名也必须是properties
// 并且在写路径的时候,路径后面的路径扩展名不能写
ResourceBundle bundle = ResourceBundle.getBundle("classinfo");
String className = bundle.getString("className");
System.out.println(className);
}
7、类加载器
7.1 定义
专门赋值加载类的命令/工具,ClassLoader
7.2 JDK中自带3个类加载器
1、启动类加载器:rt.jar
2、扩展类加载器: ext\*.jar
3、应用类加载器: classpath
7.3 假设有这样一段代码:
String s = "abc";
代码在开始执行之前,会将所需要类全部加载到JVM中,通过类加载器加载,看到以上代码类加载器会找到String.class文件,找到就加载,那么是怎么加载的呢?
1、首先通过"启动类加载器"加载
注意: 启动类加载器专门加载这个包下的东西:
C:\Program Files\Java\jdk1.8.0_101\jre\lib\rt.jar这是JDK中核心的类库
2、如果通过"启动类加载器"加载不的到时候,
就会通过扩展类加载器去加载:C:\Program Files\Java\jdk1.8.0_101\jre\lib\ext*.jar
3、如果"扩展类加载器"没有加载到,那么会通过"应用类加载器"加载。
注意:应用加载器专门加载:classpath中的类。
8、双亲委派
优先从启动类加载器中加载,这个称为"父",“父"无法加载到,再从扩展类中加载, 这个称为"母”。这就是双亲委派。
如果都加载不到才会考虑从应用类加载器中加载。直到加载到为止。