java的反射

反射是java被视为动态语言的关键,反射机制允许程序在执行期间接住reflection api获取任何类的内部信息,并能直接操作任意对象的内部属性及方法

加载完类之后,在堆的内存的方法区就产生了一个class类型的对象(一个类只有一个class对象),这个对象就包含了类的完成的结构信息,我们可以通过这个对象看到类的结构,这个对线就像是类的一面镜子,通过这个镜子可以调用类中的所有方法,所以,称之为反射

获得class对象的方法

package com.reflection;

public class test02 {

    public static   void main(String[] args)throws ClassNotFoundException
    {   //方法一 forname获得,需要知道包名
        Class c1=Class.forName("com.reflection.Student");
        System.out.println(c1.hashCode());
        //方法二 通过对象获得
        Student student=new Student();
        Class c2=student.getClass();
        System.out.println(c2.hashCode());
        //方法三 通过类名.class获得  需要知道类名
        Class c3=Student.class;
        System.out.println(c3.hashCode());
        //方法四,基本内置类型的包装类都有一个type属性
        Class c4=Integer.TYPE;
        System.out.println(c4);
        //方法五,通过子类的class类获得父类的class类
        Class  c5 = c1.getSuperclass();
        System.out.println(c5.hashCode());
    }
}
class Person
{
    public String name;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }

    public Person() {
        this.name = "人";
    }
}
class Student extends Person
{

    public Student()
    {
        this.name="学生";
    }
}
class Teacher extends Person
{

    public Teacher()
    {
        this.name="学生";
    }
}

1.通过反射获取类的名字

输出包名.类名class01.getName()

输出类名class01.getSimpleName()

package com.reflection;

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

        Class class01=Class.forName("com.reflection.User");
        System.out.println(class01.getName());
        System.out.println(class01.getSimpleName());
    }
}

2.通过反射获取类中的属性

.getFields()获得本类的public属性
.getDeclaredFields()获得本类的全部属性

.getdeclaredfield("属性名")获得本类某个属性

package com.reflection;

import java.lang.reflect.Field;

public class test04 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class class01=  Class.forName("com.reflection.User");

        Field[] fields=class01.getFields();//获得本类public属性
        for(Field field:fields)
        {
            System.out.println(field);
        }
        System.out.println("---------------------");
        fields=class01.getDeclaredFields();//获得本类的全部属性
        for(Field field:fields)
        {
            System.out.println(field);
        }
        Field name=class01.getDeclaredField("name");//获得类中的某个属性
        System.out.println(name);
    }
}

 

 3.通过反射获取类中的方法

.getMethods();//获得本类及父类的全部非private方法
.getDeclaredMethods();//获得本类全部的方法
.getMethod("getName",null);//获得某个指定的方法
.getDeclaredConstructor(int.class,String.class,String.class);//获得指定的构造函数
package com.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class test04 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class class01=  Class.forName("com.reflection.User");
        Method[] methods= class01.getMethods();//获得本类及父类的全部非private方法
        for(Method method:methods)
        {
            System.out.println("getMethods"+method);
        }

        methods= class01.getDeclaredMethods();//获得本类全部的方法
        System.out.println("---------");
        for(Method method:methods)
        {
            System.out.println("getDeclaredMethods"+method);
        }
        System.out.println("---------");

        //获得某个指定的方法
        Method getname= class01.getMethod("getName",null);
        //方法的重载,一个方法有好几个重载,所以获取的时候一定要指定参数类型
        Method setname= class01.getMethod("setName",String.class);
        System.out.println(getname);
        System.out.println(setname);
        System.out.println("---------");

        //获得指定的构造函数
        Constructor declaredConstructor =class01.getDeclaredConstructor(int.class,String.class,String.class);
        System.out.println("获得指定的构造函数"+declaredConstructor);
         //直接类名.class.方法名获取方法,不需要获得class类
         Method method= User.class.getMethod("getName",null);
    }
}

 4.通过反射 调用方法   修改属性的值

package com.reflection;

import com.sun.org.apache.bcel.internal.generic.NEW;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class test05 {
    //通过反射动态创建对象
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得class对象
        Class class1=Class.forName("com.reflection.User");

        //执行无参构造生成对象, 当类中没有无参构造函数,报错
        User user=(User) class1.newInstance();
        System.out.println(user);

        //执行有参构造生成对象
        Constructor constructor=class1.getConstructor(int.class,String.class,String.class);
        User user2 = (User) constructor.newInstance(100,"name","school");
        System.out.println("原始值"+user2);

        Method setName =class1.getMethod("setName", String.class);//两个参数,方法名,方法的参数类型
         setName.invoke(user2,"name222");//调用方法要使用invoke来调用, 方法名,invoke(对象名,方法的参数)
        System.out.println("调用方法修改name值之后的"+user2);

         Field name =class1.getDeclaredField("name");
         name.setAccessible(true); //设置不进行安全检查,使整个类的所有变量和方法在反射中可以被访问,不用管private之类的
         name.set(user2,"name333");//变量名.set(对象名,变量值);
        System.out.println("直接修改name值之后的"+user2);
    }
}

 

5.通过反射 动态 获取属性

查询参数 有注册人数、登录人数、视频播放次数等,同时只会有一个参数。

响应只有一个list数组,如果查询参数是注册人数,数组里就放注册人数的数据;如果是登录人数,数组中就放登录人数的数据。

如果不使用反射,需要写多个if (传参 = 注册人数) {.get注册人数}    太麻烦。

使用反射,可以根据查询参数 ,获取对应的数据。


/**
 * @desc 反射动态获取字段值
 * @author hs1235-zhangyuankun
 * @date 2024-09-27 10:36
 */

public class StaTest {

    public static void main(String[] args) {
        StatisticsDaily statisticsDaily = new StatisticsDaily();
        statisticsDaily.setCourseNum(100);
        statisticsDaily.setVideoViewNum(200);
        String javaFormateString = "videoViewNum";
        try {
            Class<?> statisticsDailyClazz = statisticsDaily.getClass();

            Field field = statisticsDailyClazz.getDeclaredField(javaFormateString);
            field.setAccessible(true);
            Integer count = (Integer) field.get(statisticsDaily);
            System.out.println(count);
        } catch (IllegalAccessException | NoSuchFieldException e) {

            e.printStackTrace();
        }
    }
}
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * <p>
 * 网站统计日数据
 * </p>
 *
 * @author hssx019-zhangyuankun
 * @since 2023-06-08
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class StatisticsDaily implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.ID_WORKER_STR)
    private String id;

    @ApiModelProperty(value = "统计日期")
    private String dateCalculated;

    @ApiModelProperty(value = "注册人数")
    private Integer registerNum;

    @ApiModelProperty(value = "登录人数")
    private Integer loginNum;

    @ApiModelProperty(value = "每日播放视频数")
    private Integer videoViewNum;

    @ApiModelProperty(value = "每日新增课程数")
    private Integer courseNum;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值