反射是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;
}