【笔记】Java反射机制

一、什么是反射

在运行状态中,对任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能为java语言反射机制

二、反射的三种方式

  1. 第一种方式
public class ReflectSample {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
    
        Robot r = new Robot();
        Class rc = r.getClass();
        System.out.println("Class name is " + rc.getName());
        //获取类名
    }
}

此种方式明显已经创建了对象,再进行反射,反而显得多此一举,于是一般不采用这种方式

  1. 第二种方式
public class ReflectSample {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class rc = Robot.class;
        System.out.println("Class name is " + rc.getName());
        //获取类名
    }
}

此种方式需要导入类的包,依赖性太强,一般也不采用

  1. 第三种方式
public class ReflectSample {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
    
        Class rc = Class.forName("com.imooc.javabasic.reflect.Robot");
        //根据类的全路径名获取Class
        System.out.println("Class name is " + rc.getName());
    }
}

注:Class.forName()方法需要抛出ClassNotFoundException

三、通过反射获取构造方法

public class Robot {
    private String name;

    public Robot(String name) {
        System.out.println("默认的构造方法:"+name);
    }
    public Robot(){
        System.out.println("无参的构造方法");
    }
    public Robot(int age){
        System.out.println("有一个参数的构造方法:"+age);
    }
    public Robot(String name,int age){
        System.out.println("有多个参数构造方法:"+name+","+age);
    }

    protected Robot(boolean n){
        System.out.println("受保护的构造方法:"+n);
    }
    private Robot(char c){
        System.out.println("私有的构造方法:"+c);
    }



    public void sayHi(String helloSentence){
        System.out.println(helloSentence+" "+name);
    }
    private String throwHello(String tag){
        return "Hello "+tag;
    }
    static {
        System.out.println("Hello Robot");
    }
}
public class ReflectSample {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class rc = Class.forName("com.imooc.javabasic.reflect.Robot");
        System.out.println("Class name is " + rc.getName());

        System.out.println("所有构造方法");
        Constructor[] constructors = rc.getDeclaredConstructors();
        //获取所有构造方法
        for (Constructor c:constructors){
            System.out.println(c);
        }

        System.out.println("所有公共构造方法");
        constructors = rc.getConstructors();
        //获取所有公共构造方法
        for (Constructor c:constructors){
            System.out.println(c);
        }

        System.out.println("获取公共、无参的构造方法");
        Constructor constructor = rc.getConstructor(null);
        //无参的构造方法,类型是一个null,也可以不写,此处为构造器参数的类型
        System.out.println(constructor);
        Object object = constructor.newInstance();
        //newInstance是Constructor类的方法,创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例
        Robot robot = (Robot) object;
        System.out.println(robot);

        System.out.println("获取私有的构造方法");
        constructor = rc.getDeclaredConstructor(char.class);
        System.out.println(constructor);
        constructor.setAccessible(true);//默认为false,调用私有会报错,设为true,暴力访问,忽略修饰符
        object = constructor.newInstance('男');//参数为构造方法的初始化参数
        robot = (Robot) object;
        System.out.println(robot);
    }
}

运行结果
在这里插入图片描述

四、通过反射获取成员变量

public class Robot {
    private String name;
    public int number;
    protected int age;
    char gender;

    public Robot(){}

    @Override
    public String toString() {
        return "Robot{" +
                "name='" + name + '\'' +
                ", number=" + number +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }
    public void sayHi(String helloSentence){
        System.out.println(helloSentence+" "+name);
    }
    private String throwHello(String tag){
        return "Hello "+tag;
    }
    static {
        System.out.println("Hello Robot");
    }
}
public class ReflectSample {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class rc = Class.forName("com.imooc.javabasic.reflect.Robot");
        System.out.println("Class name is " + rc.getName());

        System.out.println("获取所有公有的字段");
        Field[] fieldArray = rc.getFields();
        for(Field f : fieldArray){
            System.out.println(f);
        }
        System.out.println("获取所有的字段(包括私有、受保护、默认的)");
        fieldArray = rc.getDeclaredFields();
        for(Field f : fieldArray){
            System.out.println(f);
        }
        System.out.println("获取公有字段并调用");
        Field f = rc.getField("number");
        System.out.println(f);
        //获取一个对象
        Object obj = rc.getConstructor().newInstance();//实例化Robot,Robot robot = new Robot();
        //为字段设置值
        f.set(obj, 1);//为Robot对象中的number属性赋值–》robot.number = 1
        //验证
        Robot robot = (Robot) obj;
        System.out.println("编号:" + robot.number);


        System.out.println("获取私有字段并调用");
        f = rc.getDeclaredField("name");
        System.out.println(f);
        f.setAccessible(true);//设为true,可以访问私有
        f.set(obj,"小爱");
        System.out.println("验证:" + robot);
    }
}

运行结果
在这里插入图片描述
五、通过反射获取方法

public class Robot {
    private String name;
    public int number;
    protected int age;
    char gender;

    public Robot(){}

    @Override
    public String toString() {
        return "Robot{" +
                "name='" + name + '\'' +
                ", number=" + number +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }
    protected void show(){
        System.out.println("受保护,无参");
    }
    void play(){
        System.out.println("默认,无参");
    }
    public void sayHi(String helloSentence){
        System.out.println(helloSentence+" "+name);
    }
    private String throwHello(String tag){
        return "Hello "+tag;
    }
    static {
        System.out.println("Hello Robot");
    }
}
public class ReflectSample {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class rc = Class.forName("com.imooc.javabasic.reflect.Robot");
        System.out.println("Class name is " + rc.getName());
        
        System.out.println("获取所有的公共方法");
        rc.getMethods();
        Method[] methodArray = rc.getMethods();
        for(Method m : methodArray){
            System.out.println(m);
        }
        System.out.println("获取所有的方法");
        methodArray = rc.getDeclaredMethods();
        for(Method m : methodArray){
            System.out.println(m);
        }
        System.out.println("获取公有的sayHi()方法");
//        Robot r = (Robot) rc.newInstance();
//        r.sayHi("hello");//这句不是反射,不能调用私有方法
        Method m = rc.getMethod("sayHi", String.class);//第二个参数为形参的Class类型对象
        System.out.println(m);
        //实例化一个Robot对象
        Object obj = rc.getConstructor().newInstance();
        Robot r = (Robot) obj;
        Field name = rc.getDeclaredField("name");
        name.setAccessible(true);
        name.set(r,"Alice");
        m.invoke(obj, "welcome");
        //可获取public 以及继承实现的方法,不能获取私有

        System.out.println("获取私有的throwHello()方法");
        m = rc.getDeclaredMethod("throwHello", String.class);
        //可获取public protected private 方法,不能获取继承或实现的方法
        System.out.println(m);
        m.setAccessible(true);//解除私有限定
        Object result = m.invoke(obj, "Bob");//第一个为要调用的对象,第二个为方法的实参
        System.out.println("返回:" + result);
    }
}

运行结果
在这里插入图片描述
六、通过反射运行配置文件

public class Robot {
    public void show(){
        System.out.println("Hello!!");
    }
    static {
        System.out.println("Hello Robot");
    }
}
public class ReflectSample {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException, IOException {
//        Class rc = Class.forName("com.imooc.javabasic.reflect.Robot");
//        System.out.println("Class name is " + rc.getName());
        //通过反射获取Class对象
        Class rc = Class.forName(getValue("className"));//"com.imooc.javabasic.reflect.Robot"
        //2获取show()方法
        Method m = rc.getMethod(getValue("methodName"));//show
        //3.调用show()方法
        m.invoke(rc.getConstructor().newInstance());
    }

    public static String getValue(String key) throws IOException {
        Properties pro = new Properties();//获取配置文件的对象
        FileReader in = new FileReader(System.getProperty("user.dir")+"/src/"+"test.txt");//获取输入流
        pro.load(in);//将流加载到配置文件对象中
        in.close();
        return pro.getProperty(key);//返回根据key获取的value值
    }
}

test.txt

className = com.imooc.javabasic.reflect.Robot
methodName = show

运行结果:
在这里插入图片描述
七、总结

反射机制相关类

类名用途
Class类代表类的实体,在运行的Java应用程序中表示类和接口
Field类代表类的成员变量(成员变量也称为类的属性)
Method类代表类的方法
Constructor类代表类的构造方法

Class类
Class代表类的实体,在运行的Java应用程序中表示类和接口。

相关的方法

方法用途
getClassLoader()获得类的加载器
getClasses()返回一个数组,数组中包含该类中所有公共类和接口类的对象
getDeclaredClasses()返回一个数组,数组中包含该类中所有类和接口类的对象
forName(String className)根据类名返回类的对象
getName()获得类的完整路径名字
newInstance()创建类的实例
getPackage()获得类的包
getSimpleName()获得类的名字
getSuperclass()获得当前类继承的父类的名字
getInterfaces()获得当前类实现的类或是接口

属性相关的方法

方法用途
getField(String name)获得某个公有的属性对象
getFields()获得所有公有的属性对象
getDeclaredField(String name)获得某个属性对象
getDeclaredFields()获得所有属性对象

构造器相关的方法

方法用途
getConstructor(Class…<?> parameterTypes)获得该类中与参数类型匹配的公有构造方法
getConstructors()获得该类的所有公有构造方法
getDeclaredConstructor(Class…<?> parameterTypes)获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()获得该类所有构造方法

方法相关的方法

方法用途
getMethod(String name, Class…<?> parameterTypes)获得该类某个公有的方法或继承实现的方法
getMethods()获得该类所有公有的方法以及继承实现的方法
getDeclaredMethod(String name, Class…<?> parameterTypes)获得该类某个方法,不能获取继承实现的方法
getDeclaredMethods()获得该类所有方法,不能获取继承实现的方法

Field类
Field代表类的成员变量(成员变量也称为类的属性)。

方法用途
equals(Object obj)属性与obj相等则返回true
get(Object obj)获得obj中对应的属性值
set(Object obj, Object value)为obj设置对应属性值

Method类
Method代表类的方法。

方法用途
invoke(Object obj, Object… args)传递方法所属对象及方法实参,并调用对应的方法

Constructor类
Constructor代表类的构造器。

方法用途
newInstance(Object… initargs)根据传递的参数创建类的对象,参数为构造方法初始化参数

版权声明:本文为sinat_36416436原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。