反射

类加载器

ClassLoader:负责加载类的对象

Java运行时的内置类加载器

Bootstrap class loader 虚拟机的内置类加载器

Platform class loader:平台类加载器

System class loader:应用程序类加载器。

类加载器的继承关系:System的父类加载器为PlatformPlatform的父类加载器为Bootstrap

ClassLoader中的两个方法

Static ClassLoader getSystemClassLoader();返回用于委派的系统类加载器

ClassLoader getParent():返回父类加载器进行委派

代码示例:

//返回用于委派的系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//返回父类加载器进行委派
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);//null
View Code

 

反射:框架设计的灵魂

在程序运行期间,不引用类,直接调用类的方法

框架:半成品的软件,可以在框架的基础上进行软件的开发,简化编码

反射:将类的组成部分封装成methodfieldconstructor等对象,这就是反射机制

好处:

在程序的运行过程中操作这些对象

可以解耦,提高程序的可扩展性

 

获取class类的对象

Class.forName(“全类名”):将字节码文件加载到内存中,返回class地偶像(灵活性高,可以放到配置文件中)。

类名.class:通过类名的class属性获取(最方便)

对象.getclass():getchass()方法在object类中定义着。

对象.getName():  获取类名

代码示例:

//使用类的class属性获取
Class<Student> studentClass = Student.class;
System.out.println(studentClass);
//调用对象的getclass()方法获取
Student st=new Student();
Class<? extends Student> aClass = st.getClass();
System.out.println(aClass==studentClass);
//使用class类中的静态方法forname()获取
try {
    Class<?> aClass1 = Class.forName("Demo02.Student");
    System.out.println(  aClass1==studentClass);
} catch (ClassNotFoundException e) {
    throw new RuntimeException(e);
}
View Code

反射获取构造方法并使用

getConstructors() 获取所有公共的构造函数

getDeclaredConstructors() 获取所有构造函数

getConstructor()  根据传入参数获取构造函数

newInstance() 创建构造函数的对象

代码示例1

try {
    //获取class对象
    Class<?> aClass = Class.forName("Demo02.Student");
    //获取所有公共的构造函数
    //Constructor<?>[] constructors = aClass.getConstructors();
    //获取所有构造函数
    Constructor<?>[] constructors = aClass.getDeclaredConstructors();
    for (Constructor con : constructors) {
        System.out.println(con);
    }
    //获取无参构造函数 getConstructor中可以传入参数
    Constructor<?> constructor = aClass.getConstructor();
    System.out.println("获取无参构造函数:"+constructor);
    //创建无参构造函数的对象
    Object stu = constructor.newInstance();
    System.out.println(stu);
}
catch(Exception ex)
{}
View Code

代码示例2:带参数的构造函数

try {
    Class<?> aClass = Class.forName("Demo02.Student");
    Constructor<?> constructor = aClass.getConstructor(String.class, int.class, String.class);
    Object stu = constructor.newInstance("查理芒格", 98, "奥马哈");
    System.out.println(stu);
} catch (Exception e) {
    throw new RuntimeException(e);
}
View Code

代码示例3:反射私有的构造函数

try {
    Class<?> aClass = Class.forName("Demo02.Student");
    Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class);
    //暴力反射 私有的也可以反射
    declaredConstructor.setAccessible(true);
    Object stu = declaredConstructor.newInstance("查理芒格");
    System.out.println(stu);
} catch (Exception ex) {
    throw new RuntimeException(ex);
}
View Code

反射获取成员变量并使用

获取所有公共字段 getFields()

获取所有字段 getDeclaredFields()

获取单个字段 getField();

给成员变量赋值 set(Object, Value);

获取成员变量的值 get(Object);

代码示例:

try {
    Class<?> aClass = Class.forName("Demo02.Student");
    //获取所有公共字段
    Field[] fields = aClass.getFields();
    //获取所有字段
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field field : declaredFields) {
        System.out.println(field);
    }
    //获取单个字段
    Field address = aClass.getField("address");
    System.out.println(address);
    //创建构造函数
    Constructor<?> constructor = aClass.getConstructor();
    //创建对象
    Object stu = constructor.newInstance();
    //给成员变量赋值
    address.set(stu, "西平");
    System.out.println(stu);
} catch (Exception e) {
    throw new RuntimeException(e);
}
View Code

代码示例2

try {
    Class<?> aClass = Class.forName("Demo02.Student");
    Constructor<?> constructor = aClass.getConstructor();
    Object stu = constructor.newInstance();
    System.out.println(stu);
    Field name = aClass.getDeclaredField("name");
    name.setAccessible(true);//设置强制可访问
    name.set(stu, "查理芒格");
    Field age = aClass.getDeclaredField("age");
    age.setAccessible(true);//忽略访问修饰符的安全性检查
    age.set(stu, 98);
    Field address = aClass.getDeclaredField("address");
    address.setAccessible(true);
    address.set(stu, "奥马哈");
    System.out.println(stu);
} catch (Exception e) {
    throw new RuntimeException(e);
}
View Code

反射获取成员方法并使用

获取所有公有方法,包括继承的方法 getMethods();

获取所有本类的方法,包括私有方法 getDeclaredMethods();

获取单个方法对象 getDeclaredMethod("method1");

获取方法名 method.getName()

调用方法 method.invoke(object);

代码示例:

try {
    Class<?> aClass = Class.forName("Demo02.Student");

    Constructor<?> constructor = aClass.getConstructor();
    Object stu = constructor.newInstance();
    //获取所有公有方法,包括继承的方法
    Method[] methods = aClass.getMethods();
    //获取所有本类的方法,包括私有方法
    Method[] declaredMethods = aClass.getDeclaredMethods();
    for (Method me : declaredMethods) {
        System.out.println(me);
    }
    //获取单个方法对象
    Method method1 = aClass.getDeclaredMethod("method1");
    //调用方法
    method1.invoke(stu);
} catch (Exception e) {
    throw new RuntimeException(e);
}
View Code

代码示例2

try {
    Class<?> aClass = Class.forName("Demo02.Student");
    Constructor<?> constructor = aClass.getConstructor();
    Object stu = constructor.newInstance();
    Method function = aClass.getDeclaredMethod("function");
    function.setAccessible(true);
    function.invoke(stu);
    Method method1 = aClass.getMethod("method1");
    method1.invoke(stu);
    //获取带参方法对象
    Method method2 = aClass.getMethod("method2", String.class);
    //调用带参方法
    method2.invoke(stu,"查理芒格");
    Method method3 = aClass.getMethod("method3", String.class, int.class);
    //调用带返回参数对象
    Object o = method3.invoke(stu, "查理芒格", 98);
    System.out.println(o);
} catch (Exception e) {
    throw new RuntimeException(e);
}
View Code

运行配置文件指定内容反射

代码示例1

try {
    //加载配置文件中的数据到集合中
    Properties pro = new Properties();
    FileReader fr = new FileReader("F:\\学习\\02 JAVA\\Code\\01JavaBase\\myReflect\\src\\myclass.txt");
    pro.load(fr);
    fr.close();
    //获取集合中的类和方法
    String className = pro.getProperty("className");
    String methodName = pro.getProperty("methodName");
    Class<?> aClass = Class.forName(className);
    Constructor<?> className1 = aClass.getConstructor();
    Object obj = className1.newInstance();
    //调用类中的方法
    Method methodName1 = aClass.getMethod(methodName);
    methodName1.invoke(obj);
} catch (Exception ex) {
    throw new RuntimeException(ex);
}
View Code

配置文件myclass.txt节点如下:

className=Demo06.Teacher

methodName=teach

代码示例2

注意:需要在src下创建一个名字为pro.propertiesFile文件

 

/*
根据配置文件反射创建类对象,并执行方法
* */
try {
    Properties pro = new Properties();
    //使用类加载方式,获取class目录下的配置文件
    ClassLoader classLoader = ReflectDemo01.class.getClassLoader();
    InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
    //加载配置文件中的数据到集合中
    pro.load(resourceAsStream);
    //获取配置文件中定义的数据
    String classname=pro.getProperty("className");
    String method=pro.getProperty("methodName");
    //根据配置文件中的类和方法创建对象,调用方法
    Class<?> aClass = Class.forName(classname);
    Constructor<?> classname1 = aClass.getConstructor();
    Object obj = classname1.newInstance();
    Method method1 = aClass.getMethod(method);
    method1.invoke(obj);
}
catch(Exception ex)
{
    throw  new RuntimeException(ex);
}
View Code

 

posted on 2023-10-29 00:08  为学日损  阅读(5)  评论(0编辑  收藏  举报

导航