关于Java反射

这是本人的个人笔记,大部分内容取自Java基础之—反射(非常重要)这篇文章
写的很乱有什么不对的地方欢迎指正 海涵

1. Java反射

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

  • 通过反射机制可以将Java类中的各个元素(构造方法、成员变量、成员方法;包等)解剖为一个一个的对象
  • 要想解剖一个类,必须先要获取到该类的字节码文件对象(Class类的对象)。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

Class类

在这里插入图片描述

看半天才发现这个中文版将Class和类混淆了 ORZ

  • Class类的对象表示正在运行的Java应用程序中的类和接口。枚举是一种类,一个注释是一种接口。 每个数组也属于一个反映为Class对象的一个类,该对象由具有相同元素类型和维数的所有数组共享。 原始Java类型和关键字void也表示为Class对象。
  • Class没有公共构造函数。 相反, Class对象由Java虚拟机自动构建,通过调用类加载器中的defineClass方法。

那么JVM是如何构造一个Class对象的呢?

我们从一个类被加载的过程来分析一下:
在这里插入图片描述

以上是偏原理的部分,我们只需要知道:
可以通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法等信息;
我们来一个一个验证试试,先写一个People类

public class People {
    private String name;
    private int age;

    //People类的构造方法
    public People(){
        System.out.println("调用了public People()");
    }
    public People(String name){
        System.out.println("调用了public People(String name)");
        this.name = name;
        this.age = 20;
    }
    public People(String name, int age) {
        System.out.println("调用了public People(String name, int age)");
        this.name = name;
        this.age = age;
    }
    //方法
	public void study(){
        System.out.println("学生正在学习");
    }
    public void play(){
        System.out.println("学生正在摸鱼");
    }
    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

获取Class对象

获取Class对象有三种方法:

  1. getClass();
  2. .class
  3. forName(String className)(常用)

上代码

public void testGetClass() throws Exception{
        /*
        * 1. getClass();
        * 2. .class
        * 3. forName(String  className)(常用)
        * */
        People people = new People();
        Class cls1 = people.getClass();

        Class cls2 = People.class;

        Class cls3 = Class.forName("com.han.LeetCode.Test.People");

        System.out.println(cls1 == cls2 && cls1 == cls3 && cls2 == cls3);
    }

控制台:

true
//表示共用一个Class对象

获取构造方法

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

 3. 调用构造方法:
Constructor-->newInstance(Object... initargs)
newInstance是 Constructor类的方法。newInstance是创建了一个构造方法的声明类的新实例对象


public static void testConstructor() throws Exception {
        Class people = Class.forName("com.han.LeetCode.Test.People");
        System.out.println(people.getName());

        //一起获取所有构造器
        System.out.println("获取所有构造方法:");
        Constructor[] cons1 = people.getConstructors();
        for (Object o : cons1) {
            System.out.println(o);
        }

        //一个一个获取构造器
        System.out.println("一个一个获取构造器:");
        Constructor cons2 = people.getConstructor(String.class, int.class);
        Constructor cons3 = people.getConstructor(String.class);
        Constructor cons4 = people.getConstructor();

        System.out.println("cons2:  " + cons2);

        //调用构造器
        cons2.newInstance("han", 2);
        //等同于 new student("han", 2);

        Object obj = cons4.newInstance();
    }

控制台:

com.han.LeetCode.Test.People
获取所有构造方法:
public com.han.LeetCode.Test.People(java.lang.String,int)
public com.han.LeetCode.Test.People(java.lang.String)
public com.han.LeetCode.Test.People()
一个一个获取构造器:
cons2:  public com.han.LeetCode.Test.People(java.lang.String,int)
调用了public People(String name, int age)
调用了public People()

成员方法

/*
 * 获取成员方法并调用:
 * 
 * 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 void testMethod() throws Exception{
        Class cls1 = Class.forName("com.han.LeetCode.Test.People");
        //获取所有方法
        System.out.println("获取所有方法");
        cls1.getMethods();
        Method[] m1 = cls1.getMethods();
        for (Method method : m1) {
            System.out.println(method);
        }
        //获取指定方法
        System.out.println("获取指定方法");
        Method m2 = cls1.getMethod("play");//无参方法
        //实例化一个Class对象
        Object o1 = cls1.getConstructor().newInstance();
        //invoke函数来调用方法
        m2.invoke(o1, null);

        Method m3 = cls1.getMethod("study", String.class);//有参方法 需要两个参数,一个是要调用的对象(获取有反射),一个是实参
        Object o2 = cls1.getConstructor().newInstance();
        m3.invoke(o2, "han");
    }

控制台:

获取所有方法
public java.lang.String com.han.LeetCode.Test.People.toString()
public void com.han.LeetCode.Test.People.study(java.lang.String)
public void com.han.LeetCode.Test.People.play()
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()
获取指定方法
调用了public People()
学生正在摸鱼
调用了public People()
学生正在学习
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值