[java]反射四大类的基本用法

反射的核心就是四个类,Class,Method,Constructor,Filed,这四个类分别对应类,类的方法,类的构造方法,类的成员变量,需要先获得Class对象才能获得剩下的三个类对象

一.Class类(阅读注意区别C的大小写)

我们都知道,我们编写好的java代码文件时.java文件,要想运行这个.java文件,就要通过编译器编译,编译器会讲.java文件编译成.class文件,并且每一个类对应一个.class文件,就算一个.java文件中,定义了两个类,编译器就会将一个java文件,编译成两个.class文件.

Class类对象的内容,就是这些class文件,每一个Class类对象的内容就是其他类所有的方法,变量;现在还是有点抽象,下面的代码可以帮助理解

public static void main(String[] args){
    Class<?> c=String.class;
    //c这个Class对象获得String类的所有信息(类名、父类、实现的接口、构造方法、字段、
//方法等),我们可以通过这个对象来获取String类的相关信息。
}

Class对象的获取方法有三种

(1)通过实例化出来的对象调用getClass()方法获取;

public static void main(String[] args){
    String s=new String ();
    Class<?> cls=s.getclass();
    //通过实例化的对象获得Class对象
}

(2)通过类名.class获取;

public static void main(String[] args){
     Class<?> c=String.class;
    //通过类名获取   
}

(3)通过Class的类方法forName("文件路径")获取,这是最常用的方法;

public static void main(String[] args){
    try {
        Class<?> c = Class.forName("java.lang.String");
    } catch (ClassNotFoundException e) {
        System.out.println("Class not found: " + e.getMessage());
    }

    //通过Class类方法forName获取,forName方法会抛出异常,需要用try,catch处理
}

这个路径和声明(import)某个类的路径是一样的;

获得Class类对象后,就可以通过Class对象的newInstance()方法来实例化Class对象指向的类

public static void main(String[] args){
     try {
            Class<?> c=Class.forName("java.lang.String");
            String s1= (String) c.newInstance();
            //newInstance的返回类型为object类型,需要强转成String类型
            //通过c调用newInstance()实例化String对象
            
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    

}

二.Constructor类

Constructor类就是用来接收类对象的构造方法的类,每一个Constructor类对象都对应一个构造方法,

Class类获得Constructor对象的方法

getConstructor()和getDeclareConstructor()

getConstructor()方法只能获取到public修饰的构造方法,包括父类的构造方法

getDeclareConstructor()方法获取所有权限的构造器private,protected,public,default,但是不包括父类的构造器,但是当要使用这些不是public权限的构造器时,如果不在该权限所在的类内,需要使用setAccessible(true);方法绕开这些权限的限制才能使用这些构造器

class MyClass {
    public MyClass() {}
    protected MyClass(int x) {}
    MyClass(String s) {} // default访问修饰符
    private MyClass(double d) {}
}
public class Main{
    public static void main(String[] args){
        Class<?> c=Myclass.class;
        Constructor con1[]=c.getConstructor();
        Constructor con2[]=c.getDeclareConstructor();
        System.out.println(con1.length);//打印1
        System.out.println(con2.length);//打印4
    }
}

也可以用这两个方法来获得特定的构造方法,只需要在括号中传入特定构造函数的参数的class对象

class MyClass {
    public MyClass() {}
    protected MyClass(int x) {}
    MyClass(String s) {} // default访问修饰符
    private MyClass(double d) {}
}
public static void main(String[] args){
    Class<?> c=Myclass.class;
    Constructor con=c.getDeclareConstructor(double.class);
    //这样就获取的Myclass类中以double类型为唯一参数的构造函数
    
}

使用setAccessible方法来绕开权限限制实例化对象

class MyClass {
    public MyClass() {}
    protected MyClass(int x) {}
    MyClass(String s) {} // default访问修饰符
    private MyClass(double d) {}
}
public class Main{
    public static void main(String[] args){
        Class<?> c=Myclass.class;
        Constructor con=c.getDeclareConstructor(double.class);
        con.setAccessible(true);//设置完后,才能使用con来实例化对象
        //constructor实例化对象也是使用newInstance
        Myclass m1=(Myclass)con.newInstance(12.0);
    }
}

三.Method类

method类获取的就是类中的各种方法(除了构造方法);

实例化Method对象的方法还是需要用class对象调用

getMethod和getDeclareMethod方法,和Constructor类似,有Declare的能获得所有权限的方法,没有的只能获得公共的方法

获得特定方法需要传参数,getMethod(“方法名”,方法参数用逗号隔开);

class MyClass {
    public void func1(int a,int b){}
    private void func2(int a){}
    public static void func3(){}
}
public class Main{
    public static void main(String[] args){
        Class<?> c=Myclass.class;
        //获取func1方法
        Method method=c.getMethod("func1",int.class,int.class);
        
        
    }
}

要想调用func1方法还需要实例化一个真实的Myclass对象,然后调用invoke(对象名,参数,参数)方法就调用了Method对象中存储的Myclass对象的方法;

在Java中,调用一个类的实例方法通常有两种方式:直接使用对象(即obj.method())或使用反射机制(即method.invoke(obj, args...))。

第一种方式是直接调用,这是一种常规的方式,代码量少,执行速度相对较快。而第二种方式则是通过反射机制来实现方法的动态调用,调用过程需要借助Method对象、参数列表等信息,使用起来比较繁琐,但具备一定的灵活性和可扩展性。

另外,使用反射机制可以在运行时获取和操作类的成员变量和方法,包括私有成员、静态成员和构造方法等。这使得我们可以通过反射机制实现如框架、插件和代码生成等高级功能,从而增强了程序的灵活性和可定制性。

class MyClass {
    public void func1(int a,int b){}
    private void func2(int a){}
    public static void func3(){}
}
public class Main{
    public static void main(String[] args){
        Class<?> c=Myclass.class;
        //获取func1方法
        Method method=c.getMethod("func1",int.class,int.class);
        //实例化一个Myclass对象
        MyClass my=new MyClass();
        //通过invoke方法调用类对象的方法
        method.invoke(my,10,10);
    }
}

至于获取私有权限的方法和调用私有权限的方法和Constructor差不多,都是使用setAccessible(true)的方式

获取静态方法的过程也和上面的代码差不多,只有一点细微差别,就是因为是静态方法,所以在invoke调用的时候不需要对象,在对象的那个位置用null即可,即:

method.invoke(null,10,10);

Method方法还能获取到方法的参数类型,返回类型(getParameterTypes()、getReturnType())等

四.Field类

Field 类是 Java 反射机制中的一种重要类型,用于表示类的成员变量(也称为属性或字段)。通过 Field 对象可以获取、设置对象的某个字段的值,也可以获取、设置静态变量的值。

下面简单介绍一下 Field类中常用的几个方法:

  • getField(String name):获取指定名称的 public 字段。如果该字段不是 public 的,则抛出 NoSuchFieldException 异常。
  • getDeclaredField(String name):获取指定名称的字段,可以是 public、protected、default 或 private 访问级别的字段。如果没有找到指定字段,则抛出 NoSuchFieldException 异常。
  • getName():获取字段的名称。
  • getType():获取字段的类型,返回 Class 类型的对象。
  • getModifiers():获取字段的修饰符,返回一个整数值,每个修饰符都对应一个特定的二进制位,可通过位运算进行判断和解析。

除此之外,还有其他一些方法可以用于获取或设置字段的值,例如:

  • get(Object obj):获取指定对象的字段值。
  • set(Object obj, Object value):设置指定对象的字段值为给定值。

需要注意的是,如果要访问非 public 的字段,需要先通过 setAccessible(true) 方法将其设为可访问状态,否则会抛出 IllegalAccessException 异常。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值