Java反射机制

13 篇文章 0 订阅

Java反射机制

问题:

–如果仅仅知道一个类的类名,能否动态得到类的定义信息,包括哪些方法,属性等?

答案:可以通过反射做到

Java反射的概念和作用

Java反射的概念

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。

Java反射的作用

动态获取类的信息,进一步实现需要的功能。

Java反射相关API

我们创建一个user类,作为示例

package com.system.test;

public class User {
    public String name;
    public int age;
    private String eat;

    public User(){
        System.out.println("无参构造方法");
    }

    public User(String name){
        System.out.println("一个参数的构造方法");
    }

    private User(String name,int age){
        System.out.println("两个参数的私有构造方法");
    }

    public void eat(){
        System.out.println("无参方法");
    }

    public void eat(String name){
        System.out.println("一个参方法");
    }
    private void eat(String name,int age){
        System.out.println("两个参方法");
    }

    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 getEat() {
        return eat;
    }

    public void setEat(String eat) {
        this.eat = eat;
    }
}

Class 类型

一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被使用时都会创建一个Class对象。

Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本信息。

要使用Class类的方法,必须先获得Class类的实例

获得Class类实例的常用方法有如下三个

  1. 类名.Class
  2. new + 对象 对象.getClass()
  3. Class.forName(“路径”)
package com.system.test;

public class test {
     /*
     使用反射的前提是获得Class对象
      */
     public static void main(String[] args) throws ClassNotFoundException {
         //1.类名.Class
         Class class1 = User.class;
         System.out.println(class1);

         //2.new + 对象  对象.getClass()
         User user = new User();
         Class class2 = user.getClass();
         System.out.println(class2);
         System.out.println(class1==class2);

         //3.Class.forName("路径")
         //根据类地址,加载类信息到内存中, 创建Class对象,通过Class对象动态获取信息
         Class class3 = Class.forName("com.system.test.User");
         System.out.println(class3);
         System.out.println(class3==class1);
     }

}

Constructor 构造方法

package com.system.test;

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

public class test2 {
    /*
    使用反射的前提是获得Class对象
     */
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //根据类地址,加载类信息到内存中, 创建Class对象,通过Class对象动态获取信息
        Class c = Class.forName("com.system.test.User");


         /*
         获得类中的构造方法
         c.getConstructor()
         */

        Constructor constructor1 = c.getConstructor();//获得公告的无参构造方法
        User user = (User) constructor1.newInstance();//通过COnstructor类中的newInstance()创建对象
        System.out.println(user);

        Constructor constructor2 = c.getConstructor(String.class);//获得公共的且只有一个参数的构造方法
        User user1 = (User) constructor2.newInstance("admin");

        Constructor[] constructor3 = c.getConstructors();//获得所有的公共构造方法
        System.out.println(constructor3.length);

        Constructor constructor4 = c.getDeclaredConstructor(String.class, int.class);//获得指定的构造方法,包括私有的
        constructor4.setAccessible(true);//设置私有权限也可以被访问
        User user4 = (User) constructor4.newInstance("admin", 22);

        Constructor[] constructor5 = c.getDeclaredConstructors();//获得所有的构造方法信息,包括私有的
        System.out.println(constructor5.length);
    }
}

Field 属性

–public Field getField(String name)

–通过指定Field名字,返回Field实例

–注意Field的访问权限

package com.system.test;

import com.system.bean.Admin;

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

public class test3 {
    /*
    使用反射的前提是获得Class对象
     */
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        User user = new User();
        user.setName("admin");
        user.setAge(22);
        user.setEat("粑粑");
        System.out.println(test(user));
        System.out.println(test(new com.system.bean.Admin()));
    }

    public static String test(Object obj) throws IllegalAccessException {
        Class c = obj.getClass();
        Field[] fs = c.getFields();//获取所有公开属性
        Field[] fs1 = c.getDeclaredFields();//获取所有属性包含私有
        String s ="";
        for (Field f : fs1) {
            f.setAccessible(true);
            s+=f.getName()+":"+f.get(obj)+",";
        }
        return s.substring(0,s.length()-1);
    }
}

Method 方法

Method类将类中的方法进行封装,可以动态获得方法的信息,例如

–getName:获得方法名字

–getParameterTypes:获得方法参数类型

除了动态获得方法信息外,Method还能动态调用某一个对象的具体方法

–invoke(Object obj, Object… args) :使用obj调用该方法,参数为args

Method实例都是通过Class类的方法获得

–Method getMethod(String name, Class… parameterTypes) :通过指定方法名,参数类型,返回一个Method实例

package com.system.test;

import com.system.bean.Admin;

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

public class test4 {
    /*
    使用反射的前提是获得Class对象
     */
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
         /*
          使用反射前提是获得Class对象
         */
        //想调用User类中的 eat
        test("com.system.test.User","eat");
        test("com.system.bean.Admin","getId");
    }

    public static void test(String className,String methodName) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class c = Class.forName(className);//Class中封装类的信息
        Object obj = c.newInstance();//创建一个对象
        Method m = c.getMethod(methodName);//获得类中指定名称的方法
        m.setAccessible(true);
        m.invoke(obj);//执行调用方法
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值