Java反射

Java反射

Class类

类是对象,类是java.lang.Class类的实例对象。
任何一个类都是Class的实例对象,这个实例对象有三种表示方式。

  1. Class c1 = Foo.class;
  2. 已知该类的对象,通过getClass方法Class c2 = foo1.getClass();
  3. 第3种方式

    Class c3 = null;
    try {
        c3 = Class.forName("com.imooc.reflect.Foo");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    

可以通过类的类型来创建类的对象实例,即通过c1 or c2 or c3创建Foo的实例。

    try {
        Foo foo = (Foo) c1.newInstance();//需要有无参数的构造方法
    } catch (InstantiationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }

动态加载类
编译时刻加载类是静态加载类,运行时刻加载类是动态加载类。
new 创建对象是静态加载类,在编译时刻就需要加载所有的可能使用到的类。

    //动态加载类,在运行时刻加载
    Class c = Class.forName(args[0]);
    //通过类类型,创建该类对象
    c.newInstance();

基本数据类型,void关键字 ,都存在类类型。如下:

    Class c1 = int.class;//int的类类型
    Class c2 = String.class;

    System.out.println(c1.getName());
    System.out.println(c2.getName());
    System.out.println(c2.getSimpleName());//不包含包名的类名称

输出结果为:

int
java.lang.String
String

Method

获取方法信息
getName() 获取类的名称
getMethods()方法获取的是所有的public的函数,包括父类继承而来的

Method[] ms = c.getMethods();

Method类,表示方法对象,一个成员方法就是一个Method对象。

  • 获取方法的返回值类型的类类型 getReturnType()

    Class returnType = ms[i].getReturnType();
    
  • 获取方法的名称 getName()

  • 获取参数类型getParameterTypes(),返回的是参数列表的类型的类类型

getDeclaredMethods()返回这个类或接口的全部方法,但不包括由超类继承了的方法。

如下,获取Class的所有方法:

/**
 * 打印一个类的所有方法
 * @param cl
 */
public static void printMethods(Class cl) {
    Method[] methods = cl.getDeclaredMethods();
    for(Method m : methods){
        Class retType = m.getReturnType();
        String name = m.getName();

        System.out.print("     ");
        String modifiers = Modifier.toString(m.getModifiers());
        if (modifiers.length() > 0) {
            System.out.print(modifiers + " ");
        }
        System.out.print(retType.getName() + " " + name + "(");

        Class[] paramTypes = m.getParameterTypes();
        for (int i = 0; i < paramTypes.length; i++) {
            if (i > 0) {
                System.out.print(", ");
                System.out.print(paramTypes[i].getName());
            }
        }
        System.out.println(");");
    }
}

getModifiers返回一个用于描述构造器、方法或域的修饰符的整型数值。

Field

获取成员变量信息
成员变量也是对象,java.lang.reflect.Field封装了关于成员变量的操作。

  • getFields() 获取的是所有的public的成员变量的信息

    Field[] fs = c.getFields();
    
  • getDeclaredFields() 获取的是该类自己声明的成员变量的信息

Field方法

  • getType()得到成员变量的类型的类类型

        //得到成员变量的类型的类类型
        Class fieldType = field.getType();
        String typeName = fieldType.getName();
    
  • getName() 得到成员变量的名称

    String fieldName = field.getName();
    

如下,打印所有的域:

/**
 * 打印所有的域
 * @param cl 类
 */
public static void printFields(Class cl) {
      Field[] fields = cl.getDeclaredFields();

      for (Field f : fields)
      {
         Class type = f.getType();
         String name = f.getName();
         System.out.print("     ");
         String modifiers = Modifier.toString(f.getModifiers());
         if (modifiers.length() > 0) System.out.print(modifiers + " ");         
         System.out.println(type.getName() + " " + name + ";");
      }
}

}

Constructor

获取构造函数信息
java.lang.reflect.Constructor封装了构造函数的信息。

  • getConstructors() 获取所有的public的构造函数的信息
  • getDeclaredConstructor() 获取所有的构造函数

         Constructor[] cs = c.getConstructors();
         for (Constructor constructor : cs) {
            System.out.println(constructor.getName());
            //获取构造函数的参数列表
            Class[] paramTypes = constructor.getParameterTypes();
            for(Class class1 : paramTypes){
                System.out.println(class1.getName());
            }
        }
    

如下,打印Class的所有的构造方法:

/**
 * 打印一个类的所有构造器方法
 * @param cl 类
 */
public static void printConstructors(Class cl) {
    Constructor[] constructors = cl.getDeclaredConstructors();
    for (Constructor c : constructors) {
        String name = c.getName();
        System.out.print("     ");
        //修饰符
        String modifiers = Modifier.toString(c.getModifiers());
        if (modifiers.length() > 0) {
            System.out.print(modifiers + " ");
        }
        System.out.print(name+"(");

        //参数类型
        Class[] paramTypes = c.getParameterTypes();
        for (int i = 0; i < paramTypes.length; i++) {
            if (i > 0) {
                System.out.print(", ");
            }
            System.out.print(paramTypes[i].getName());
        }
        System.out.println(");");
    }
}

方法的反射

  • 如何获取某个方法?
    方法的名称和方法的参数列表才能唯一决定某个方法
  • 方法反射的操作
    method.invoke(对象,参数列表)

例子:

package com.imooc.reflect;

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

public class ClassDemo {

    public static void main(String[] args) {

        //获取print(int,int)方法
        A a1 = new A();
        Class c = a1.getClass();
        //获取方法 名称和参数列表来决定
        try {
            //Method m = c.getMethod("print", new Class[]{int.class, int.class});
            Method m = c.getMethod("print", int.class, int.class);

            //方法的反射操作
            try {
                //方法如果没有返回值返回null,有返回值返回具体的返回值
                //Object object =  m.invoke(a1, new Object[]{10, 20});
                Object object =  m.invoke(a1, 10, 20);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                e.printStackTrace();
            }

        } catch (NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }



    }

}

class A{
    public void print(int a, int b){
        System.out.println(a+b);
    }
    public void print(String a, String b){
        System.out.println(a.toUpperCase()+","+b.toLowerCase());
    }
}

在运行时使用反射分析对象

利用反射机制可以查看在编译时还不清楚的对象域。

如下:

    Employee harry = new Employee("Harry Hacker", 3500, 1989, 10, 10);
    Class cl = harry.getClass();
    Field f;
    f = cl.getDeclaredField("name");
    f.setAccessible(true);
    Object v = f.get(harry);

f.setAccessible(true);是因为name是一个私有域,如果没有这段话get方法会抛出异常。

setAccessible为反射对象设置可以访问标志。flag为true表示屏蔽Java语言的访问检查,使得对象的私有属性也可以被查询和设置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值