资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

java反射笔记-创新互联

Java反射笔记
  • Java反射
    • 反射概述
    • 获取Class类的对象
    • 反射获取构造方法并使用
    • 反射获取成员变量并使用
    • 反射获取成员方法并使用
    • 反射获取注解
  • 反射练习
    • 需求一:创建一个集合泛型为Integer,添加一个字符串元素
    • 需求二:通过配置文件运行类中的指定方法
    • 需求三,使用注解替代配置文件

在上一篇 Java注解笔记中,我们简单了解了Java注解。但是,注解到底如何工作我们还不清楚,在学习了反射之后,我们就可以让注解做很多事情了

创新互联建站专注于网站建设|网站维护|优化|托管以及网络推广,积累了大量的网站设计与制作经验,为许多企业提供了网站定制设计服务,案例作品覆盖墙体彩绘等行业。能根据企业所处的行业与销售的产品,结合品牌形象的塑造,量身定制品质网站。Java反射 反射概述

Java反射机制:是指在运行时去获取一个类的变量和方法信息,然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。

获取Class类的对象

我们要想通过反射去使用一个类,首先我们要获取到该类的字节码文件对象,也就是类型为Class类型的对象

这里我们介绍三种方式获取Class类型的对象

  • 使用类的class属性来获取该类对应的Class对象
  • 调用对象的getClass()方法,返回该对象所属类对应的Class对象
    • 该方法是Object类中的方法,所有的Java对象都可以调用该方法
  • 使用Class类中的静态方法forName(String className),该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名的路径

Student类

public class Student {private String name;
    int age;
    public String address;

    public Student() {}
    private Student(String name) {this.name = name;
    }

    Student(String name,int age) {this.name = name;
        this.age = age;
    }

    public Student(String name, int age, String address) {this.name = name;
        this.age = age;
        this.address = address;
    }

    private void function() {System.out.println("function");
    }

    public void method1 () {System.out.println("method");
    }

    public void method2 (String s) {System.out.println("method" + s);
    }
    public String method3 (String s, int i) {return s + "," + i;
    }

    @Override
    public String toString() {return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}

测试反射类

public class ReflectTest {public static void main(String[] args) throws ClassNotFoundException {// 使用类的class属性来获取该类对应的Class对象
        Classc1 = Student.class;
        Classc2 = Student.class;
        System.out.println(c1);
        System.out.println(c1 == c2);// true

        System.out.println("==========");

        // 调用对象的getClass()方法,返回该对象所属类对应的Class对象
        Student s = new Student();
        Classc3 = s.getClass();
        System.out.println(c1 == c3);// true

        System.out.println("==========");

        // 使用Class类中的静态方法forName(String className)
        Classc4 = Class.forName("com.example.fanshe.Student");
        System.out.println(c1 == c4);// true
    }
}
反射获取构造方法并使用
  • 调用Class类的getConstructors()方法,该方法返回所有公共构造函数数组
public class ReflectTest {public static void main(String[] args) {// 得到Student类的字节码文件对象
        ClassstudentClass = Student.class;
        Constructor[] constructors = studentClass.getConstructors();
        for (Constructorcon : constructors) {System.out.println(con);
        }
    }
}
  • 调用Class类的getDeclaredConstructors()方法,该方法返回所有构造函数数组
public class ReflectTest {public static void main(String[] args) {// 得到Student类的字节码文件对象
        ClassstudentClass = Student.class;
        Constructor[] constructors = studentClass.getDeclaredConstructors();
        for (Constructorcon : constructors) {System.out.println(con);
        }
    }
}
  • 调用Class类的getConstructor()方法,该方法返回指定公共构造函数
public class ReflectTest {public static void main(String[] args) throws NoSuchMethodException,
            InvocationTargetException, InstantiationException, IllegalAccessException {// 得到Student类的字节码文件对象
        ClassstudentClass = Student.class;
        // 拿到无参公共构造方法
        Constructorconstructor = studentClass.getConstructor();
        // 使用反射方式创建对象
        Student student = constructor.newInstance();
        System.out.println(student);
    }
}
public class ReflectTest {public static void main(String[] args) throws NoSuchMethodException,
            InvocationTargetException, InstantiationException, IllegalAccessException {ClassstudentClass = Student.class;
        // 拿到无参公共构造方法
        //Constructorconstructor = studentClass.getConstructor();
        // 拿到3个参数的构造方法
        Constructorconstructor = studentClass.getConstructor(String.class,
                int.class, String.class);
        // 使用反射方式创建对象
        Student student = constructor.newInstance("小米", 19, "广东");
        System.out.println(student);
    }
}
  1. 基本数据类型同样可以通过class属性得到对应的Class类型

  2. newInstance()方法:创建反射类对应的类的实例

  • 调用Class类的getDeclaredConstructor()方法,该方法返回指定构造函数
public class ReflectTest {public static void main(String[] args) throws NoSuchMethodException,
            InvocationTargetException, InstantiationException, IllegalAccessException {// 得到Student类的字节码文件对象
        ClassstudentClass = Student.class;
        // 拿到指定构造函数
        Constructorconstructor = studentClass.getDeclaredConstructor(String.class);
        // 取消访问检查,以便使用私有构造方法创建对象
        constructor.setAccessible(true);
        Student student = constructor.newInstance("小米");
        System.out.println(student);
    }
}
public void setAccessible(boolean flag)

这个方法用于取消访问检查,暴力反射机制

  • 参数说明
  1. flag:值为true时取消访问检查,值为false时,不取消
反射获取成员变量并使用
Class类方法说明
public Field[] getFields()返回所有公共字段数组
public Field[] getDeclaredFields()返回所有字段数组
public Field getField(String name)返回指定公共字段
public Field getDeclaredField(String name)返回指定字段
public class ReflectTest {public static void main(String[] args) throws NoSuchMethodException,
            InvocationTargetException, InstantiationException,
            IllegalAccessException, NoSuchFieldException {// 得到Student的字节码对象
        ClassstudentClass = Student.class;
        // 得到address字段
        Field addressField = studentClass.getDeclaredField("address");
        // 得到name字段
        Field nameField = studentClass.getDeclaredField("name");
        // 得到无参构造方法
        Constructorconstructor = studentClass.getConstructor();
        // 创建对象
        Student student = constructor.newInstance();
        // 取消访问检查
        nameField.setAccessible(true);
        // 为字段设置值
        addressField.set(student, "西安");
        nameField.set(student, "小米");
        // 打印
        System.out.println(student);
    }
}
public void set(Object obj, Object value)

为字段设置值

参数说明:

  1. obj:为要为哪个对象设置值
  2. value:值是多少
反射获取成员方法并使用
Class类方法说明
public Method[] getMethods()返回所有公共方法数组(包含继承过来的)
public Method[] getDeclaredMethods()返回所有方法数组(不包含继承的)
public Method getMethod(String name, Class… parameterTypes)返回指定的公共方法
public Method getDeclaredMethod(String name, Class… parameterTypes)返回指定的方法
public class ReflectTest {public static void main(String[] args) throws NoSuchMethodException,
            InvocationTargetException, InstantiationException,
            IllegalAccessException {// 得到Student的字节码对象
        ClassstudentClass = Student.class;
        // 得到method1方法
        Method method = studentClass.getDeclaredMethod("method1");
        // 得到method2方法
        Method method2 = studentClass.getMethod("method2", String.class);
        // 得到method3方法
        Method method3 = studentClass.getMethod("method3", String.class, int.class);
        // 得到function方法
        Method function = studentClass.getDeclaredMethod("function");
        // 得到公共的无参构造方法
        Constructorconstructor = studentClass.getConstructor();
        Student student = constructor.newInstance();
        // 调用方法
        method.invoke(student);
        method2.invoke(student, "s");
        Object s = method3.invoke(student, "s", 1);
        System.out.println(s);
        function.setAccessible(true);
        function.invoke(student);
    }
}
public Object invoke(Object obj, Object... args)

调用方法

参数说明:

  1. obj:调用方法的对象
  2. args:方法的形参
反射获取注解
Class类方法说明
public< A extends Annotation >A getAnnotation(Class< A >annotationClass)获取指定的注解信息
反射练习 需求一:创建一个集合泛型为Integer,添加一个字符串元素
public class ReflectTest {public static void main(String[] args) throws NoSuchMethodException,
            InvocationTargetException, InstantiationException,
            IllegalAccessException, NoSuchFieldException {ArrayListarrays = new ArrayList<>();

        ClassaClass = arrays.getClass();

        Method add = aClass.getMethod("add", Object.class);

        add.invoke(arrays, "word");
        System.out.println(arrays);
    }
}
需求二:通过配置文件运行类中的指定方法
public class ReflectTest {public static void main(String[] args) throws NoSuchMethodException,
            InvocationTargetException, InstantiationException,
            IllegalAccessException, ClassNotFoundException, IOException {// 加载数据
        Properties prop = new Properties();
        FileReader fr = new FileReader("src\\main\\java\\com\\example\\fanshe\\class.properties");
        prop.load(fr);
        fr.close();

        String className = prop.getProperty("className");
        String methodName = prop.getProperty("methodName");

        // 得到字节码文件对象
        ClassaClass = Class.forName(className);
        // 得到无参构造方法
        Constructorconstructor = aClass.getConstructor();
        // 创建对象
        Object o = constructor.newInstance();
        // 得到method1方法
        Method method1 = aClass.getMethod(methodName);
        // 调用方法
        method1.invoke(o);
    }
}

class.properties文件如下:

className=com.example.fanshe.Student
methodName=method1
需求三,使用注解替代配置文件
@MyAnnotation(className = "com.example.fanshe.Student",methodName = "method1")
public class ReflectTest {public static void main(String[] args) throws NoSuchMethodException,
            InvocationTargetException, InstantiationException,
            IllegalAccessException, ClassNotFoundException, IOException {// 通过注解来运行指定类中的指定方法
        ClassreflectTestClass = ReflectTest.class;
        MyAnnotation annotation = reflectTestClass.getAnnotation(MyAnnotation.class);
        String className = annotation.className();
        String methodName = annotation.methodName();

        // 得到字节码文件对象
        ClassaClass = Class.forName(className);
        // 得到无参构造方法
        Constructorconstructor = aClass.getConstructor();
        // 创建对象
        Object o = constructor.newInstance();
        // 得到method1方法
        Method method1 = aClass.getMethod(methodName);
        // 调用方法
        method1.invoke(o);
    }
}

注解定义如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {String className();
    String methodName();
}

这就是框架常用到的技术了,后期在谈到框架时我们在深入讨论,那么今天就先到这里了

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


新闻名称:java反射笔记-创新互联
本文URL:http://cdkjz.cn/article/dgghjo.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220