Java反射

本文详细介绍了Java反射机制的核心概念,包括类、方法、成员变量的获取与操作,以及如何利用反射实现动态加载类、获取方法信息、了解集合泛型的本质。通过实例代码演示,深入理解反射机制在Java开发中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《一》、Class类的使用

一、类也是对象,是java.lang.Class的实例对象
二、任何一个类都是Class类的实例对象,有三种表示方式:(Class的构造方法是私有的,只允许JVM调用,因此无法通过关键词new创建Class的实例对象)
  • 1、通过类名.class创建,也即说明任何一个类都有一个静态的成员变量class
    • 如:Class c1 = Foo.class;
  • 2、 通过类的对象的getClass方法
    • 如:Foo foo1 = new Foo();
      Class c2 = foo1.getClass();
  • 3、通过Class的forName方法传入类的全限定名获取

    • 如:Class c3 = null;
      c3 = Class.forName("com.imooc.reflect.Foo");
      (会有ClassNotFoundException)
  • c1、c2表示的Foo类的类类型(class type)

    • 万事万物皆对象,类也是对象,是Class类的实例对象,这个对象称为类的类类型
    • 可以通过类的类类型创建该类的对象
      § 如:Foo foo2 = (Foo)c1.newInstance();
  • 一个类只能是Class的一个实例对象,无论通过三种方法中的哪一种获取都一样

《二》、动态加载类

  • 三种方法中,c1、c2为静态加载类(编译时加载),而c3为动态加载类(运行时加载)
  • 1、new 出来的都是静态加载类,一招出错,全盘皆输;

  • 2、动态加载类

   Class c = Class.forName(args[0]);

   OfficeAble oa = (OfficeAble)c.newInstance();//OfficeAble定义的功能类型接口

《三》、获取方法信息

  • 1、基本的数据类型,关键字都存在类类型。
    例子:int.class String.class Double.class
    Class c = obj.getClass();
    方法也是对象:
  • Method类:方法对象
  Method[] ms = c.getMethods();//获取所有public方法,包括父类继承的方法
  ms.getName();//方法的名称
  Class returnType = ms.getReturnType();
  returnType.getName();//返回值类型
  Class[] paramTypes = ms.getParameterTypes();//参数的类类型数组

方法实例

public class ClassUtil {

    public static void printClassMessage(Object obj){
        //要获取类的信息,首先要获取类的类类型
        Class c = obj.getClass();//传递的是哪个子类的对象,c就是该子类的类类型

        //获取类的名称
        System.out.println("类的名称是:" + c.getName());
        /*
         * Method类,方法对象
         * 一个成员方法就是一个Method对象
         * getMethods()获取的是所有public函数,包括父类继承而来的
         * getDeclaredMethods()获取的是该类自己声明的方法,不问访问权限
         */
        Method[] ms = c.getMethods(); //c.getDeclaredMethods();
        for (Method method : ms) {
            //得到方法的返回值类型
            System.out.print(method.getReturnType().getSimpleName()+" ");
            //得到方法的名称
            System.out.print(method.getName()+"(");
            //得到参数类型---->得到的参数列表类型的类类型
            Class[] paramTypes = method.getParameterTypes();
            if(paramTypes.length==0){
                //若没有参数,则直接返回右括号
                System.out.println(")");
            }else {
                int i = 0;
                //遍历打印到倒数第二个参数
                for(;i < paramTypes.length-1;i++){
                    System.out.print(paramTypes[i].getSimpleName()+",");
                }
                //打印出最后一个参数和右括号,并换行,可以避免多出一个逗号
                System.out.println(paramTypes[i].getSimpleName()+")");
            }
        }
    }
}

《四》、获取成员变量构造函数信息

  • 获取类的成员对象
    Field[] = c.getFields()
  • 获取该类自己生命所有成员变量的信息
    Field[] = c.getDeclaredFieds()

  • 1、成员变量也是对象

    • java.lang.reflect.Field
    • Filed类封装了成员变量的操作
    • getFields()方法获取的是所有public成员的信息
  • 2、构造函数也是对象;

    • java.lang.Constructor中封装了构造函数的信息;
    • getConstructors获取所有的public的构造函数;
    • getDeclaredConstructors得到所有的构造函数;
Class c = obj.getClass();
// Field[]  field = c.getFields();
Field[]  fields = c.getDeclaredFields();
for (Field field : fields) {
    // 得到成员变量的类型的类类型
    Class fieldType = field.getType();
    System.out.print("成员变量类型:"+fieldType.getName());
    // 得到成员变量名称
    String  fieldName = field.getName();
    System.out.print("   成员变量名称:"+fieldName);
    System.out.println();
}

《五》、方法反射的基本操作

  • (1)如何获取某个方法
    方法的名称和方法的参数列表才能唯一决定某个方法
  • (2)方法的反射的操作
    mentod.invoke(对象,参数列表)
A a1= new A();
Class c = a1.getClass();
Method method = c.getMethod("print",new Class[]{int.class,int.class});
// Method method = c.getMethod("print",int.class,int.class); // 另一种写法

method.invoke(a1);//等同于a1.print();的效果

《六》、通过反射了解集合泛型的本质

import java.lang.reflect.Method;
import java.util.ArrayList;
/**
 * 通过反射了解集合泛型的本质
 * @author shm
 *
 */
public class MethodDemo02 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("hello");
        list.add(20);

        ArrayList<String> list1 = new ArrayList<String>();
        list1.add("hello");
        //list1.add(20);//这个加入是错误的:The method add(int, String) in the type ArrayList<String> is not applicable for the arguments (int)

        Class c1 = list.getClass();
        Class c2 = list1.getClass();
        System.out.println(c1==c2);
        //反射的操作都是编译后的操作

        /**
         * c1=c2结果返回TRUE说明编译后集合的泛型是去泛型化的
         * java中集合的泛型,是防止错误输入的,只在编译阶段有效,绕过编译后就无效了
         * 验证:我们可以通过反射操作来绕过编译
         */
        try {
            Method method = c2.getMethod("add", Object.class);
            method.invoke(list1, 20);
            System.out.println(list1);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }



    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值