【Java 笔记 使用反射访问类的结构】

本文深入探讨Java反射机制,涵盖Person类的创建与调用,详细解析通过反射获取类的构造函数、属性、方法及私有成员,同时介绍反射在获取属性性质与方法结构的应用,并讨论封装与反射的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建一个Person类

public class Person {
    private String name;
    int age;
    public Person(){
        name="小心";
        age=10;
    };
    public Person(String name , int age) {
        this.name = name;
        this.age = age;
    }
    private Person(String name ) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
   public String toString(){
        return name+"..."+age;
    }
    public int hashCode(){
        return this.name.hashCode()+this.age;

    }
    public  boolean equals(Object o){
      /*  if(o==null){
            return false;
        }*/
        if(this==o)
            return true;
        if(o instanceof Person){
            Person other=(Person) o;
            return this.name.equals(other.name) && this.age==other.age;
        }
        return false;
    }
    private  void show(){
        System.out.println("我是私有方法");
    }

}

直接调用Person类

  反射之前,可以创造类的对象,通过对象调用其内部属性、方法,但是不可以调用其内部私有结构:比如私有属性、私有方法和私有构造器。
static void test(){
    Person p=new Person();
    System.out.println(p.toString());
}

获取Class类的四种方式

static void reflect() throws ClassNotFoundException {
    System.out.println("------获取反射的四种方式------");
     //方式一:
    Class cls1=Person.class;

     //方式二:使用较少,通常利用反射去构造类实例,此方式却是利用类实例得到反射
    Person p=new Person();
    Class cls2=p.getClass();

     //方式三:推荐使用此方式
    Class cls3=Class.forName("Test.Person");//类的路径名
    //Class cls3=Class.forName("java.lang.String");

    //方式四:使用类加载器
    ClassLoader loader=Reflectiontest.class.getClassLoader();
    Class cls4=loader.loadClass("Test.Person");

    System.out.println(cls1==cls2);//true
    System.out.println(cls2==cls3);//true
    System.out.println(cls3==cls4);//true
//对于数组,只要元素类型跟数组维度一致,则获取的Class类相同
 }
 

通过反射访问公共构造函数、属性、方法

//通过反射实现上述对公共构造函数、属性、方法的操作
static void test1() throws Exception {
    Class cls=Person.class;
   //调用构造函数
    Constructor cons=cls.getConstructor(String.class,  int.class);
    Object obj=cons.newInstance("阿反",1);
    Person newP=(Person) obj;
    //调用默认构造函数
    // Object obj1=cls.newInstance();
    //Person newP=(Person) obj1;

    System.out.println(newP.toString());

    //调用指定方法
    Method hashcode= cls.getDeclaredMethod("hashCode");
    System.out.println(hashcode.invoke(newP));
    Method ageset= cls.getDeclaredMethod("setAge", int.class);
    ageset.invoke(newP,3);
    System.out.println(newP.toString());

    //调用指定属性
    Field age=cls.getDeclaredField("age");
    age.set(newP,18);
    System.out.println(newP.toString());
}

通过反射调用类的私有属性和方法

 static void test2() throws Exception {
        System.out.println("----------通过反射调用私有属性和方法---------");
        Class cls=Person.class;

//        Constructor [] con=cls.getDeclaredConstructors();
//        for ( Constructor c:con){
//            System.out.println(c.getName());
//        }

        //调用私有构造函数
        Constructor cons=cls.getDeclaredConstructor(String.class);
        cons.setAccessible(true);//设置允许访问
        Person newP=(Person)cons.newInstance("私有的阿反");
        System.out.println(newP.toString());

        //调用私有方法
        Method show=cls.getDeclaredMethod("show");
        show.setAccessible(true);//设置允许访问
        show.invoke(newP);

        //调用私有属性
        Field name=cls.getDeclaredField("name");
        name.setAccessible(true);//设置允许访问
        name.set(newP,"开心的阿反");
        System.out.println(newP.toString());
    }

通过反射获取属性的性质(权限修饰符 数据类型 变量名)

static void test3() throws Exception {
    System.out.println("----------通过反射查询权限修饰符 数据类型 变量名---------");
    Class cls = Person.class;
    Field [] fs=cls.getDeclaredFields();

    for (Field f:fs ){
        int modify=f.getModifiers();// 0: default   1:public  2:private
        Class classf=f.getType();//获取数据类型
        String name=f.getName();//获取变量名
        System.out.println(modify+" "+ Modifier.toString(modify) +" "+classf.getName()+ " "+name);
    }
}

通过反射获取方法的结构

static void test4() throws Exception {
    System.out.println("--m--------通过反射查询类的方法结构---------");
    Class cls = Person.class;
    //获取运行时类及其所有父类中的public方法
    Method []  mm=cls.getMethods();

    System.out.println("获取运行时类及其所有父类中的public方法");
    for (Method m:mm ) {
        System.out.println(m);
    }

    //获取运行时类声明的所有方法,不包括父类方法
    Method [] ms=cls.getDeclaredMethods();
    System.out.println();
    System.out.println("获取运行时类声明的所有方法的结构,不包括父类方法");
    for (Method m:ms ){
        int modify=m.getModifiers();// 0: default   1:public  2:private
        Class classf=m.getReturnType();//获取返回类型
        String name=m.getName();//获取方法名
        Class [] paramerType=m.getParameterTypes();//获取参数
        String paramers=null;
        if (!(paramerType==null && paramerType.length==0)) {
            for (Class css : paramerType) {
                if (paramers==null){paramers=css.getName();
                }else {
                    paramers = " " + paramers + css.getName();
                }
            }
        }
        System.out.println(modify+" "+ Modifier.toString(modify) +" "+classf.getName()+ " "+name+"("+paramers+")");
    }

如何看待封装跟反射

它们之间并不矛盾,封装给出的是如何使用的最好提示,而反射是解决能否可以调用,在开发中是可以不按照封装的提示来进行操作的。
注意:在可以直接创建对象的地方尽量不要使用反射创建对象,因为反射往往要到了运行期才能检查出代码错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值