文章目录
1、Class类实例
1.1、获取Class类的实例(四种方法)
- 若已知具体的类,通过类的class属性获取
Class clazz = String.class;
- 通过类的实例对象获取
User user = new Child();
Class<? extends User> aClass = user.getClass();
- 已知全类名,通过Class类的静态方法forName()获取
Class clazz = Class.forName("java.lang.String");
- 系统类加载对象或自定义加载器对象 加载指定路径下的类型
ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass("类的全类名");
1.2、类加载器(四种)
1.2.1、介绍
(1)启动类加载器(引导类加载器,Bootstrap ClassLoader)
-
它用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar或sun.boot.class.path路径下的内容)。用于提供JVM自身需要的类。
-
并不继承自java.lang.ClassLoader,没有父加载器。
-
出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类
-
加载扩展类和应用程序类加载器,并指定为他们的父类加载器。
(2)扩展类加载器(Extension ClassLoader)
-
Java语言编写,由sun.misc.Launcher$ExtClassLoader实现。
-
继承于ClassLoader类
-
父类加载器为启动类加载器
-
从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录下加载类库。如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。
(3)应用程序类加载器(系统类加载器,AppClassLoader)
- 用于加载用户自定义的类
(4)用户自定义类加载器(了解)
1.2.2、使用
查看某个类是哪个类加载器加载的
ClassLoader classloader = Class.forName("exer2.ClassloaderDemo").getClassLoader();
//如果是根加载器加载的类,则会得到null
ClassLoader classloader1 = Class.forName("java.lang.Object").getClassLoader();
获取某个类加载器的父加载器
ClassLoader parentClassloader = classloader.getParent();
2、获取运行时类的完整结构
- 获取类的 父类class对象
- 获取类的接口数组
- 获取类的属性、属性数组
- 获取类的方法、方法数组
- 获取类的构造方法、构造方法数组
User user = new Child();
user.test1();
// TODO 获取类对象
Class<? extends User> aClass = user.getClass();
//TODO 获取类的父类对象
Class<?> superclass = aClass.getSuperclass();
System.out.println(superclass.getSimpleName());
//TODO 获取类的接口数组
Class<?>[] interfaces = aClass.getInterfaces();
System.out.println(interfaces.length);
//TODO 获取类的属性
Field f = aClass.getField("xxxx"); //public
Field f1 = aClass.getDeclaredField("xxxx"); //所有权限的属性
//TODO 获取类的所有属性数组
Field[] fields = aClass.getFields(); //public
Field[] declaredFields = aClass.getDeclaredFields(); //所有权限的属性
//TODO 获取类的方法
Method method = aClass.getMethod("test2");
Method method2 = aClass.getDeclaredMethod("test2");
Method[] methods = aClass.getMethods();
Method[] declaredMethods = aClass.getDeclaredMethods();
//TODO 获取类的构造方法 对象
Constructor<? extends User> constructor = aClass.getConstructor();
// 获取类的所有 公共构造方法
Constructor<?>[] constructors = aClass.getConstructors();
3、调用运行时类的指定结构(方法、属性)
- 调用运行时类的构造器 (newInstance)
- 调用运行时类的 方法(invoke)
- 给运行时对象赋值 (set)、
现有员工类,通过反射创建员工类实例 并 为其赋值和调用方法
//员工
class Emp{
public String account;
public String password;
//判断登录
public boolean login(){
if ("admin".equals(account) && "admin".equals(password)){
return true;
}else {
return false;
}
}
}
通过反射创建员工类实例 并 为其赋值和调用方法
- invoke: 第一个参数为对象,后面的参数为 该方法的参数
- invoke(Object obj, Object… args)
- set: 第一个参数为对象, 第二个参数为属性值
- set(Object obj, Object value)
- Field类其实还要get方法,用于获取运行时对象的属性值。
- get(Object obj)
public static void main(String[] args) throws Exception{
//TODO 反射练习
//员工登录功能
//构造 Emp类对象
Class empClass = Emp.class;
//Class<?> aClass = Class.forName("hhb.Java基础练习.对象与反射.practice1.Emp");
//Class<? extends Emp> aClass1 = new Emp().getClass();
//获取构造器
Constructor declaredConstructor = empClass.getDeclaredConstructor();
//构建对象,引用为Object类
Object emp = declaredConstructor.newInstance();
//获取对象的属性
Field account = empClass.getField("account");
Field password = empClass.getField("password");
//给属性赋值 , 给emp对象赋值, set
account.set(emp,"admin");
password.set(emp,"admin");
//登录, 获取登录方法
Method loginMethod = empClass.getMethod("login");
//调用方法 invoke
Object result = loginMethod.invoke(emp);
System.out.println(result);
}