JAVA基础-反射

发布于 2024-08-07  1199 次阅读


反射

JAVA-准动态语言

JAVA和C、C++一样是静态语言,运行时不能像Python,js一样改变程序的结构
如js中的eval("var x = 1")或python中的def square(x);square = lambda x : x*x
但是JAVA可以通过反射机制获得类似动态语言的特性
java的反射机制允许通过调用反射API,在程序运行期间,获取类的任何内部信息,直接操作对象的任意内部属性和方法

通过获取类的Class对象

通过反射可以获取类的Class对象,从而获取类的信息(变量、方法等)

方法一

可以通过类名获取类在内存中的class对象

Class c = Class.forName();

方法二

可以通过Object的getClass方法获得一个对象对应的类的Class对象

Class c1 = new student(2,"wm").getClass();

方法三

可以通过类名.class来获取类的Class对象

Class c2 = student.class;

获取父类Class对象

通过本类的Class对象获取父类的Class对象

Class c3 = c.getSuperclass;
public class testForName {
    public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException {
        Class c = Class.forName("student");
        Class c1 = new student(2,"wm").getClass();
        Class c2 = student.class;
        //c,c1,c2指向同一个Class对象
        System.out.println(c2.getMethod("getName"));

        Class c3 = c.getSuperclass();
        System.out.println(c3.getMethod("getJob"));
    }
}

class person{
    private String job = "工人";

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }
}
class student extends person{
    private int id = 0;
    private String name = "mak";

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public void setId(int id) {
        this.id = id;
    }

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

获取类的信息

获取类名:c.getName()
获取本类及其父类的方法:c.getMethod("getId")
获取类的public变量:Field[] Fields = c.getFields()
获取类的所有变量:Field[] Fields = c.getDeclaredFields()
Field id = c.getDeclaredFields("id")
等等,用的时候跟进去看一下就行

动态操作反射创建的对象

可以通过获得的Class对象去修改属性、执行方法等
以这个student类为例:

class student {
    private int id = 0;
    private String name = "mak";

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setId(int id) {
        this.id = id;
    }

    void test(String name){
        System.out.println("hello,"+this.name+" and "+name);
    }

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

通过反射创建对象

Class stuclass = Class.forName("student");
student stu = (student)stuclass.newInstance();

通过反射创建有带参构造器的对象

Constructor constr = stuclass.getConstructor(int.class,String.class); //获取类的构造器,参数:构造器参数类型的class
student stu1 = (student) constr.newInstance(12,"Tom");

执行对象的方法

Method stname = stuclass.getMethod("setName", String.class); //获取类的方法,参数:方法名,方法参数类型的Class
stname.invoke(stu1,"wm"); //invoke(激活):执行函数,参数:(用于执行函数的对象,函数参数)
Method hello = stuclass.getDeclaredMethod("test", String.class);
hello.invoke(stu1,"abc");

mak_image

操作对象属性

Field stuid = stuclass.getDeclaredField("name");
stuid.setAccessible(true); //对于修改private属性,要先关闭程序安全检测(默认为true)
stuid.set(stu1,"wm1111"); //set修改,参数:要修改属性的对象,修改后的值
hello.invoke(stu1,"def");

mak_image

反射获取泛型

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
class test11{
    //参数是泛型
    public void test01(Map<String,Integer> map, List<student> list){
        System.out.println("test01");
    }

    //返回值是泛型
    public Map<String,Integer> test02(){
        System.out.println("test02");
        return null;
    }

}

public class test1 {
    public static void main(String args[]) throws NoSuchMethodException {

        //获取泛型参数的类:
        Method mtd = test11.class.getMethod("test01", Map.class,List.class);
        Type[] gnpt = mtd.getGenericParameterTypes(); //获取参数泛型
        for (Type gt:gnpt){
            System.out.println("#"+gt);
            if(gt instanceof ParameterizedType){
                Type[] atas = ((ParameterizedType) gt).getActualTypeArguments(); //获得真实参数类
                for(Type ata : atas){
                    System.out.println(ata);
                }
            }
        }

        //获取泛型返回值的类:
        Method mtd1 = test11.class.getMethod("test01", Map.class,List.class);
        Type gt = mtd.getGenericReturnType(); //获取返回值泛型
        System.out.println("#"+gt);
        if(gt instanceof ParameterizedType){
            Type[] atas1 = ((ParameterizedType) gt).getActualTypeArguments(); //获得真实参数类
            for(Type ata : atas1){
                System.out.println(ata);
            }

        }
    }
}

mak_image

反射获取注解

import java.lang.annotation.*;
import java.lang.reflect.AnnotatedArrayType;
import java.lang.reflect.Field;

public class testGetAnno {
    public static void main(String args[]) throws ClassNotFoundException, NoSuchFieldException {
        //获取类的注解
        Class cl1 = Class.forName("stus");
        Annotation[] annos = cl1.getAnnotations(); //获得注解
        for(Annotation anno : annos){
            System.out.println("类的注解:"+anno);
        }

        //获取注解的value值
        stuTable stutanno = (stuTable) cl1.getAnnotation(stuTable.class); //获取指定注解类的注解
        String value = stutanno.value();
        System.out.println("注解的value:"+value);

        //获取类的指定属性指定的注解
        Field f = cl1.getDeclaredField("name");
        stuField stutanno1 = f.getAnnotation(stuField.class); 
        System.out.println("属性Name的注解中,columnName的值是:"+stutanno1.columnName());

    }

}
@stuTable(value = "高三十班")
class stus{
    @stuField(columnName = "clm_id",Type = "int",length = 10)
    private int id;
    @stuField(columnName = "clm_id",Type = "int",length = 2)
    private int age;
    @stuField(columnName = "clm_id",Type = "varchar",length = 10)
    private String name;

    public stus(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

//类名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface stuTable{
    String value();
}

//属性注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface stuField{
    String columnName();
    String Type();
    int length();
}

mak_image

A web ctfer from 0RAYS
最后更新于 2024-08-24