java基础-反射

java基础-反射

一. 概述

再运行时去获取一个类的变量和方法信息. 通过获取到的信息来创建对象,调用方法.这种方法称为反射.

二. 获取Class类的对象

  • 使用类的class属性来获取该类对应的class对象
  • 调用对象的getClass()方法, 返回该对象所属类对应的Class对象,该方法时Object类中的方法,所有的java对象都可以调用该方法
  • 使用Class类中的静态方法forName(String className), 该方法传入类的全路径

三.代码获取Class类对象

package com.qiyun.reflect;

public class Student {
    private String addr;
    public String name;
    int age;

    public Student() {

    }

    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private Student(String addr) {
        this.addr = addr;
    }

    public Student(String name, int age, String addr) {
        this.name = name;
        this.age = age;
        this.addr = addr;
    }

    private void function() {
        System.out.println("function");
    }

    public void method1() {
        System.out.println("method1");
    }

    public void method2(String s) {
        System.out.println("method2 " + s);
    }

    public String method3(String s, int i) {
        return s + "," + i;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name= '" + name  +
                ",age=" + age +
                "address=" + addr+
                '}' ;
    }

}

public class test_demo {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<Student> c1 = Student.class;
        System.out.println(c1);

        Student stu = new Student();
        Class<? extends Student> stuClass = stu.getClass();
        System.out.println(stuClass);

        Class<?> aClass = Class.forName("com.qiyun.reflect.Student");
        System.out.println(aClass);
    }
}
class com.qiyun.reflect.Student
class com.qiyun.reflect.Student
class com.qiyun.reflect.Student

四.通过反射获取构造方法

  • Constructor<?>[] cons = aClass.getConstructors() //获取公共构造方法对象的数组
  • Constructor<?>[] cons = aClass.getDeclaredAnnotations()//获取所有构造方法对象的数组
  1. 获取公共的构造方法对象
Class<?> aClass = Class.forName("com.qiyun.reflect.Student");
//Class类的对象表示正在运行的java应用程序的类和接口.
Constructor<?>[] cons = aClass.getConstructors();//返回类里面公共的构造方法
for (Constructor con:cons) {
	System.out.println(con);
}
//获取所有构造方法对象
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor ano: declaredConstructors) {
            System.out.println(ano);
        }
  1. 使用获取的构造方法对象
        //返回一个Constructor对象,该对象反应该类对应的构造方法,参数是需要获取的构造
        //方法的个数和数据类型对应的字节码对象
        Constructor<?> con = aClass.getConstructor();
        Object obj = con.newInstance();
        System.out.println(obj.toString());//调用重写的toString()
Student{name= 'null,age=0address=null}
  1. 获取单个构造方法对象
Constructor<?> con = aClass.getConstructor(String.class,int.class,String.class);
Object obj = con.newInstance("xioami",18,"beijin");
 System.out.println(obj.toString());
Student{name= 'xioami,age=18address=beijin}
  1. 获取私有构造方法
        Constructor<?> de = aClass.getDeclaredConstructor(String.class);
        de.setAccessible(true); //暴力反射 IllegalAccessException
        Object object = de.newInstance("beijin");
        System.out.println(object.toString());
Student{name= 'null,age=0address=beijin}

五. 反射获取成员变量

Field[] fields = aClass.getFields(); //获取公共成员变量
Field[] fields = aClass.getDeclaredFields() //获取全部成员变量

Field field = aClass.getField(“name”); //获取公有变量name

Field field = aClass.getDeclareField(“addr”);//获取私有变量addr

Constructor<?> de = aClass.getDeclaredConstructor(String.class);
de.setAccessible(true);
Object object = de.newInstance("beijin");
System.out.println(object.toString());

Field addr = aClass.getDeclaredField("addr");
addr.setAccessible(true);
addr.set(object,"xian");
System.out.println(object.toString());

六.反射获取成员方法

  1. 获取全部的公共成员方法
        Method[] methods = aClass.getMethods();
        for (Method method: methods
             ) {
            System.out.println(method);
        }
public java.lang.String com.qiyun.reflect.Student.toString()
public java.lang.String com.qiyun.reflect.Student.method3(java.lang.String,int)
public void com.qiyun.reflect.Student.method2(java.lang.String)
public void com.qiyun.reflect.Student.method1()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
获取所有的方法,包括父类的
  1. 获取有参数有返回值的方法
Class<?> aClass = Class.forName("com.qiyun.reflect.Student");
Constructor<?> c = aClass.getConstructor();
Object obj = c.newInstance();
   
Method method3 = aClass.getMethod("method3", String.class, int.class);
Object m3 = method3.invoke(obj,"xiaomi",18);//调用了obj对象的method3对应的method3();
System.out.println(m3);

七. 反射使用

  1. 反射越过泛型检查
ArrayList<Integer> array = new ArrayList<Integer>();

Class<? extends ArrayList> arrayClass = array.getClass();
Method add = arrayClass.getMethod("add", Object.class);
add.invoke(array,"hello");
add.invoke(array,"world");
System.out.println(array);
[hello, world]
  1. 反射运行配置文件指定的类
className=com.qiyun.stu.Student
methodName=study
package com.qiyun.stu;

public class Student {
    public void study(){
        System.out.println("好好学习");
    }
}
package com.qiyun.stu;

public class Teacher {
    public void teach(){
        System.out.println("用爱呵护未来");
    }
}
package com.qiyun.stu;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Properties properties = new Properties();
        FileReader fileReader = new FileReader("day01\\src\\class.txt");
        properties.load(fileReader);
        fileReader.close();

        String className = properties.getProperty("className");
        String method = properties.getProperty("methodName");

        Class<?> aClass = Class.forName(className);
        Constructor<?> constructor = aClass.getConstructor();
        Object obj = constructor.newInstance();
        Method study = aClass.getMethod(method);
        study.invoke(obj);
    }
}

好好学习

八. 总结

  1. java代码在计算机中的三个阶段
    在这里插入图片描述

  2. 反射存在的意义

  • 框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
  • 反射:将类的各个组成部分封装为其他对象,这就是反射机制
    • 好处:
      1. 可以在程序运行过程中,操作这些对象。
      2. 可以解耦,提高程序的可扩展性。
  1. 获取Class对象的方式

    1. Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
      • 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
    2. 类名.class:通过类名的属性class获取
      • 多用于参数的传递
    3. 对象.getClass():getClass()方法在Object类中定义着。
      • 多用于对象的获取字节码的方式
    • 结论:
      同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
  2. Field:成员变量

    • 操作:
      1. 设置值

        • void set(Object obj, Object value)
      2. 获取值

        • get(Object obj)
      3. 忽略访问权限修饰符的安全检查

        • setAccessible(true):暴力反射
  3. Constructor:构造方法

    • 创建对象:
      • T newInstance(Object… initargs)
      • 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
  4. Method:方法对象

    • 执行方法:

      • Object invoke(Object obj, Object… args)
    • 获取方法名称:

      • String getName:获取方法名
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值