美文网首页
Java基础---反射

Java基础---反射

作者: 皮多堡 | 来源:发表于2020-07-25 21:59 被阅读0次

Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。
另外,很多优秀的开源框架都是通过反射完成的,比如Spring框架。所以学好反射也是Java程序员的必备基础节能

1.获取类信息

/**
 * 通过反射获取Class类信息三种方式
 * 1.Class.forName()
 * 2.示例名.getClass()
 * 3.类名.class
 * @author haopeng
 * @date 2020-07-25 21:22
 */
public class ClassReflectTest {

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

        Class<?> forName = Class.forName("demo.reflect.ClassReflectTest");
        System.out.println("第一种:Class.forName():"+forName.getName());

        ClassReflectTest classReflectTest = new ClassReflectTest();
        Class aClass = classReflectTest.getClass();
        System.out.println("第二种:示例名.getClass():"+ aClass.getName());

        Class<?> staticName = ClassReflectTest.class;
        System.out.println("第三种:Class.forName():"+staticName.getName());
    }
}

2.获取构造方法

1).批量的方法:
  public Constructor[] getConstructors():所有"公有的"构造方法
  public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
2).获取单个的方法,并调用:
  public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
  public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

调用构造方法:Constructor-->newInstance(Object... initargs)

示例:

public class ConstructorReflectTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Class.forName("demo.reflect.ReflectTarget");
        //1.获取所有的公有构造方法
        System.out.println("**********************所有公有构造方法*********************************");
        Constructor[] conArray = clazz.getConstructors();
        for(Constructor c : conArray){
            System.out.println(c);
        }
        //2.获取所有构造方法
        System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
        conArray = clazz.getDeclaredConstructors();
        for(Constructor c : conArray){
            System.out.println(c);
        }
        //3.获取单个带参数的公有方法
        System.out.println("*****************获取公有、有两个参数的构造方法*******************************");
        Constructor con = clazz.getConstructor(String.class, int.class);
        System.out.println("con = " + con);
        //4.获取单个私有的构造方法
        System.out.println("******************获取私有构造方法*******************************");
        con = clazz.getDeclaredConstructor(int.class);
        System.out.println("private con = " + con);
        System.out.println("******************调用私有构造方法创建实例*******************************");
        //暴力访问(忽略掉访问修饰符)
        con.setAccessible(true);
        ReflectTarget reflectTarget = (ReflectTarget) con.newInstance(1);
    }
}

public class ReflectTarget extends ReflectTargetOrigin{
    //---------构造函数-----------
    //(默认的带参数构造函数)
    ReflectTarget(String str) {
        System.out.println("(默认)的构造方法 s = " + str);
    }

    //无参构造函数
    public ReflectTarget() {
        System.out.println("调用了公有的无参构造方法 。。。");
    }

    //有一个参数的构造函数
    public ReflectTarget(char name) {
        System.out.println("调用了带有一个参数的构造方法,参数值为 " + name);
    }

    //有多个参数的构造函数
    public ReflectTarget(String name, int index) {
        System.out.println("调用了带有多个参数的构造方法,参数值为【目标名】: " + name + " 【序号】" + index);
    }
    //受保护的构造函数
    protected ReflectTarget(boolean n){
        System.out.println("受保护的构造方法 n :" + n);
    }
    //私有的构造函数
    private ReflectTarget(int index){
        System.out.println("私有的构造方法 序号:" + index);
    }

    //**************字段*******************//
    public String name;
    protected int index;
    char type;
    private String targetInfo;
    @Override
    public String toString(){
        return "ReflectTarget [name=" + name + ", index=" + index + ", type=" + type
                + ", targetInfo=" + targetInfo + "]";
    }
    //***************成员方法***************//
    public void show1(String s){
        System.out.println("调用了公有的,String参数的show1(): s = " + s);
    }
    protected void show2(){
        System.out.println("调用了受保护的,无参的show2()");
    }
    void show3(){
        System.out.println("调用了默认的,无参的show3()");
    }
    private String show4(int index){
        System.out.println("调用了私有的,并且有返回值的,int参数的show4(): index = " + index);
        return "show4result";
    }

    public static void main(String[] args) throws ClassNotFoundException {
        //第一种方式获取Class对象
        ReflectTarget reflectTarget = new ReflectTarget();
        Class reflectTargetClass1 = reflectTarget.getClass();
        System.out.println("1st : " + reflectTargetClass1.getName());
        //第二种方式获取Class对象
        Class reflectTargetClass2 = ReflectTarget.class;
        System.out.println("2nd: " + reflectTargetClass2.getName());
        //判断第一种方式获取的class对象和第二种方式获取的是否是同一个
        System.out.println(reflectTargetClass1 == reflectTargetClass2);
        //第三种方式来获取Class对象
        Class reflectTargetClass3 = Class.forName("demo.reflect.ReflectTarget");
        System.out.println("3rd: " + reflectTargetClass3.getName());
        System.out.println(reflectTargetClass2 == reflectTargetClass3);
    }
}

public class ReflectTargetOrigin {
    String defaultMember = "default";
    public String publicMember = "public";
    protected String protectedMember = "protected";
    private String privateMember = "private";
}

3.获取字段

1.批量的
       1).Field[] getFields():获取所有的"公有字段"
       2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
2.获取单个的:
       1).public Field getField(String fieldName):获取某个"公有的"字段;
       2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)

设置字段的值:
     Field --> public void set(Object obj,Object value): 参数说明:1.obj:要设置的字段所在的对象;2.value:要为字段设置的值;

示例:

public class FieldReflectTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class reflectTargetClass = Class.forName("demo.reflect.ReflectTarget");
        //1.获取所有公有的字段
        System.out.println("************获取所有公有的字段********************");
        Field[] fieldArray = reflectTargetClass.getFields();
        for (Field f : fieldArray){
            System.out.println(f);
        }
        //2.获取所有的字段
        System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
        fieldArray = reflectTargetClass.getDeclaredFields();
        for (Field f : fieldArray){
            System.out.println(f);
        }
        //3.获取单个特定公有的field
        System.out.println("*************获取公有字段并调用***********************************");
        Field f = reflectTargetClass.getField("name");
        System.out.println("公有的field name : " + f);
        ReflectTarget reflectTarget = (ReflectTarget)reflectTargetClass.getConstructor().newInstance();
        //4.给获取到的field赋值
        f.set(reflectTarget, "待反射一号");
        //5.验证对应的值name
        System.out.println("验证name : " + reflectTarget.name);
        //6.获取单个私有的Field
        System.out.println("**************获取私有字段targetInfo并调用********************************");
        f = reflectTargetClass.getDeclaredField("targetInfo");
        System.out.println(f);
        f.setAccessible(true);
        f.set(reflectTarget, "13810592345");
        System.out.println("验证信息" + reflectTarget);
    }
}

4.获取方法

1.批量的:
      public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
      public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
 2.获取单个的:
      public Method getMethod(String name,Class<?>... parameterTypes): 参数:name : 方法名;Class ... : 形参的Class类型对象
      public Method getDeclaredMethod(String name,Class<?>... parameterTypes)

   调用方法:
      Method --> public Object invoke(Object obj,Object... args):参数说明: obj : 要调用方法的对象;args:调用方式时所传递的实参;

示例:

public class MethodCollector {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1、获取Class对象
        Class reflectTargetClass = Class.forName("demo.reflect.ReflectTarget");
        //2、获取所有公有方法
        System.out.println("***************获取所有的public方法,包括父类和Object*******************");
        Method[] methodArray = reflectTargetClass.getMethods();
        for(Method m : methodArray){
            System.out.println(m);
        }
        //3、获取该类的所有方法
        System.out.println("***************获取所有的方法,包括私有的*******************");
        methodArray = reflectTargetClass.getDeclaredMethods();
        for(Method m : methodArray){
            System.out.println(m);
        }
        //4、获取单个公有方法
        System.out.println("***************获取公有的show1()方法*******************");
        Method m = reflectTargetClass.getMethod("show1", String.class);
        System.out.println(m);
        //5、调用show1并执行
        ReflectTarget reflectTarget = (ReflectTarget)reflectTargetClass.getConstructor().newInstance();
        m.invoke(reflectTarget, "待反射方法一号");
        //6、获取一个私有的成员方法
        System.out.println("***************获取私有的show4()方法******************");
        m = reflectTargetClass.getDeclaredMethod("show4", int.class);
        System.out.println(m);
        m.setAccessible(true);
        String result = String.valueOf(m.invoke(reflectTarget, 20));
        System.out.println("返回值 : " + result);
    }
}

总结

0. 获取类Class
Class.forName()
示例名.getClass()
类名.class

1.构造器
public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法
public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
调用构造方法:Constructor-->newInstance(Object... initargs)

2.字段
Field[] getFields():获取所有的"公有字段"
Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
public Field getField(String fieldName):获取某个"公有的"字段;
public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)

3.方法
public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
public Method getMethod(String name,Class<?>... parameterTypes):
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
调用方法:Method --> public Object invoke(Object obj,Object... args):

相关文章

  • Java基础:反射

    反射注解动态代理相关阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 ...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • Java基础:注解

    系列阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 1. 概述 注解...

  • Java高级知识

    反射 sczyh30 深入解析Java反射(1) - 基础深入解析Java反射(2) - invoke方法深入探究...

  • Java基础:动态代理

    系列阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 概述 在运行时,...

  • java 反射进阶

    1.java反射基础 2.java反射进阶 上一节介绍了反射基础,本节介绍更深入的反射概念。 1.获取不到Clas...

  • java 反射基础

    1.java反射基础 2.java反射进阶 反射的两个显著的作用 反编译: .class —> .java 通过...

  • Java基础:类加载器

    系列阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 1. 什么是类加...

  • 硬核干货!备战阿里,字节,腾讯 2020最新Java最常见面试题

    Java Java 基础这部分一些简单的问题就直接没有放上来。 基础: Java 反射?反射有什么缺点?你是怎么理...

网友评论

      本文标题:Java基础---反射

      本文链接:https://www.haomeiwen.com/subject/ienmlktx.html