Java 反射 -- 框架设计的灵魂

Java 反射

Java程序在计算机经历的三个阶段:

Java 反射 -- 框架设计的灵魂_第1张图片
JAV代码在计算机的三个阶段.JPG

反射的机制:

​ 将类的各个组成部分封装为其他对象

获取Class对象的方式

  • Class.forName("全类名"):将字节码文件加载进内存,返回Class对象。
Class.forName("com.cc.domain.Person");
//多用于配置文件,将类名定义在配置文件中。读取文件,加载类
  • 类名.class:通过类名的属性class获取
Person.class;
//多用于参数的传递
  • 对象.getClass():getClass()方法在Object类中定义着。
Person p = new Person();
p.getClass();
//多用于对象的获取字节码的方式

Class对象的获取功能

1. 获取成员变量们
    //public修饰的成员变量
    Field[] getFields() //所有
    Field getField(String name) //指定
    //不考虑修饰符
    Field[] getDeclaredFields() //指定 
    Field getDeclaredField(String name) //所有
2. 获取构造方法们
    //public修饰
    Constructor[] getConstructors()  
    Constructor getConstructor(类... parameterTypes)  
    //不考虑修饰符
    Constructor getDeclaredConstructor(类... parameterTypes)  
    Constructor[] getDeclaredConstructors()  
3. 获取成员方法们:
    //public修饰
    Method[] getMethods()  
    Method getMethod(String name, 类... parameterTypes)  
    //不考虑修饰符
    Method[] getDeclaredMethods()  
    Method getDeclaredMethod(String name, 类... parameterTypes)  

4. 获取全类名    
    String getName()  

具体实例代码:

Test类

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class RelfectDemo01 {
    public static void main(String[] args) throws Exception {
        Class personClass = Class.forName("com.itheima.domain.Person");
//      获取指定名称的public修饰的成员变量
        Field sexField = personClass.getField("sex");
//      获取指定名称的成员变量
        Field nameField = personClass.getDeclaredField("name");
//      给成员变量设置值
//      自定义对象
        Person p = new Person();
        sexField.set(p,"男");
        Object sexF = sexField.get(p);
        System.out.println(p);
        System.out.println(sexF);
//      暴力反射
        nameField.setAccessible(true);
        nameField.set(p,"张无忌");
        Object zwj = nameField.get(p);
        System.out.println(p);

        System.out.println("*************构造器*************");

        Constructor constructorHaveCan = personClass.getConstructor(String.class, int.class);

        System.out.println(constructorHaveCan);

//        用来创建对象
//       带参
        Object zhangSanFeng = constructorHaveCan.newInstance("张三丰", 18);
        System.out.println(zhangSanFeng);

//       空参

        Constructor constructorNoCan = personClass.getConstructor();

        Object zhangWuJi = constructorNoCan.newInstance();
        System.out.println(zhangWuJi);
//        简化
        Object no = personClass.newInstance();

//        成员方法
        System.out.println("***************成员方法****************");

        Method eatMethod = personClass.getMethod("eat");
        Person p3 = new Person();
        eatMethod.invoke(p3);
        System.out.println("----------------------------");

        Method eatHCMethod = personClass.getMethod("eat", String.class);
        Person p4 = new Person();
        eatHCMethod.invoke(p4,"饭");
        String nameMethod = eatHCMethod.getName();
        System.out.println("方法名为:"+nameMethod);

        System.out.println("*****************类名*****************");

        String nameName = personClass.getName();
        System.out.println(nameName);
    }
}

Person类

package com.itheima.domain;

public class Person {
    private String name;
    private int age;
    public String sex;

    public Person() {
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    public void eat(){
        System.out.println("eat.....");
    }
    public void eat(String name){
        System.out.println("吃"+name);
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}

反射框架案例

需求:

  • 可以创建任意类的对象,可以执行任意方法
  • 在配置文件中有全类名和类中的方法,在只修改配置文件。
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

public class ReflectFrame {

    public static void main(String[] args) throws Exception {

//    加载配置文件

//    1.创建Properties对象
        Properties prop = new Properties();  //Properties本身就是一个集合
//    2.加载配置文件,转换为一个集合

//    3.获取class目录下的配置文件
        ClassLoader classLoader = ReflectFrame.class.getClassLoader(); //获取字节码文件的类加载器
//    4.获取资源路径,获取资源对相应的字节流
        InputStream is = classLoader.getResourceAsStream("tro.properties");
//    5.加载
        prop.load(is);

//        获取配置文件中定义的数据
        String className = prop.getProperty("className");
        String methodName = prop.getProperty("methodName");

//        使用反射,加载该类进内存
        Class cls = Class.forName(className);
//        创建对象
        Object p1 = cls.newInstance();
        Method method = cls.getMethod(methodName);
        method.invoke(p1);
    }
}

配置文件

  • tro.properties
className = com.itheima.domain.Student
methodName = eat

你可能感兴趣的:(Java 反射 -- 框架设计的灵魂)