Java的反射

本文主要围绕以下几个点来详解反射:
1、反射机制是什么?
2、反射机制能做什么?
3、Java中反射的API以及应用

1.反射机制是什么?

借用百度百科的定义:

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

之所以强调属性、方法,是因为属性、方法是开发者对于一个类最关注的两个部分。实际上通过反射,不仅仅可以获知类的属性、方法,还可以获知类的父类、接口、包等信息

至于反射的原理,不难,Java类加载机制中讲到了,一个类在加载的时候,会在内存中生成一个代表这个.class文件的java.lang.Class对象,.classs文件里面就包含了描述这个类的信息的一切内容。至于.class文件,是由Java编译器(注意是Java编译器,指的不仅仅是Javac)编译而来的,是编译原理的领域。

2. 反射机制能做什么?

下面第二个问题,反射机制能做什么?
反射机制主要提供了以下功能:
1. 在运行时判断任意一个对象所属的类;
2. 在运行时构造任意一个类的对象;
3. 在运行时判断任意一个类所具有的成员变量和方法;
4. 在运行时调用任意一个对象的方法;
5. 生成动态代理。

3.发射机制的API以及应用实例

Class类库与java.lang.reflect类库一起对反射机制提供了支持。

1.通过一个实例对象获取完整的包名和类名

@Test
public void test1(){
    ReflectTest reflectTest = new ReflectTest();
    System.out.println(reflectTest.getClass().getName());
}
/**output~
test.ReflectTest
*/

2.实例化class类对象

@Test
public void test2() throws ClassNotFoundException {
    Class<?> class1 = null;
    class1 = Class.forName("test.ReflectTest");
    System.out.println("类名称是:"+class1);
}
/**output~
类名称是:class test.ReflectTest
*/

3.获取一个对象的父类与实现的接口

@Test
public void test3() throws ClassNotFoundException {
    Class<?> clazz = null;
    clazz = Class.forName("test.ReflectTest");

    //获取父类
    Class<?> parentClass = clazz.getSuperclass();
    System.out.println("clazz的父类为:" + parentClass.getName());

    // 获取所有的接口
    Class<?> intes[] = clazz.getInterfaces();
    System.out.println("clazz实现的接口有:");
    for (int i = 0; i < intes.length; i++) {
        System.out.println((i + 1) + ":" + intes[i].getName());
    }
}
/**output~
clazz的父类为:java.lang.Object
clazz实现的接口有:
1:java.io.Serializable
*/

4.获取某一个类中全部构造函数 以及 实例化一个类对象

@Test
public void test4() throws Exception {
    Class<?> class1 = null;
    class1 = Class.forName("test.User");
    // 第一种方法,实例化默认构造方法,调用set赋值
    User user = (User) class1.newInstance();
    user.setAge(23);
    user.setName("LouLou");
    System.out.println(user);
    // 结果 User [age=20, name=Rollen]
    // 第二种方法 取得全部的构造函数 使用构造函数赋值
    Constructor<?> cons[] = class1.getConstructors();
    // 查看每个构造方法需要的参数
    for (int i = 0; i < cons.length; i++) {
        Class<?> clazzs[] = cons[i].getParameterTypes();
        System.out.print("cons[" + i + "] (");
        for (int j = 0; j < clazzs.length; j++) {
            if (j == clazzs.length - 1)
                System.out.print(clazzs[j].getName());
            else
                System.out.print(clazzs[j].getName() + ", ");
        }
        System.out.println(")");
    }
    // 结果
    // cons[0] (int, java.lang.String)
    //cons[1] (java.lang.String)
    //cons[2] ()
    user = (User) cons[0].newInstance(23, "LouLou");
    System.out.println(user);
    // 结果 User [age=23, name=LouLou]
    user = (User) cons[1].newInstance("LouLou");
    System.out.println(user);
    // 结果 User [age=0, name=LouLou]
}

//实体类
class User {
    private int age;
    private String name;
    public User() {
        super();
    }
    public User(String name) {
        super();
        this.name = name;
    }
    public User(int age, String name) {
        super();
        this.age = age;
        this.name = name;
    }
    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;
    }
    @Override
    public String toString() {
        return "User [age=" + age + ", name=" + name + "]";
    }
}

5.获取某个类的全部属性

class Parent {
    private Integer pf1=1;
    protected Integer pf2=2;
    public Integer pf3=3;
    Integer pf4=4;
}

public class ReflectTest extends Parent implements Serializable{
    private String field1="field1";
    protected String field2="field2";
    public String field3="field3";
    String field4="field3";

    @Test
    public void test5() throws Exception {
        Class<?> clazz = null;
        clazz = Class.forName("test.ReflectTest");

        System.out.println("===============本类属性===============");
        Field[] field = clazz.getDeclaredFields();//获取本类的全部属性(不包括父类或则实现的接口)
        for (int i = 0; i < field.length; i++) {
            // 权限修饰符
            int mo = field[i].getModifiers();
            String priv = Modifier.toString(mo);
            // 属性类型
            Class<?> type = field[i].getType();
            System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";");
        }

        System.out.println("==========本类或则实现的接口或者父类的public的属性==========");
        // 取得实现的接口或者父类的属性
        Field[] filed1 = clazz.getFields();
        for (int j = 0; j < filed1.length; j++) {
            // 权限修饰符
            int mo = filed1[j].getModifiers();
            String priv = Modifier.toString(mo);
            // 属性类型
            Class<?> type = filed1[j].getType();
            System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");
        }
    }
}
/**output~
===============本类属性===============
private java.lang.String field1;
protected java.lang.String field2;
public java.lang.String field3;
 java.lang.String field4;
==========本类或则实现的接口或者父类的public的属性==========
public java.lang.String field3;
public java.lang.Integer pf3;
*/

从上面的运行结果可知:
Class.getDeclaredFields()方法放回的是当前类里面的所有属性。Class.getFields()返回的是当前类已及父类和实现的接口的所有public修饰的属性。

6.获取某个类的全部方法

private void testtttt(){

}
/**
 * 获取某个类的全部方法
 * @throws Exception
 */
@Test
public void test6() throws Exception {
    Class<?> clazz = Class.forName("test.ReflectTest");
    Method[] method = clazz.getMethods();//获取本类以及继承类\实现接口的所有public修饰的方法
    //Method[] method = clazz.getDeclaredMethods();//只获取本类的所有方法
    for(int i=0; i<method.length; i++){
        int mod = method[i].getModifiers();
        String modifier = Modifier.toString(mod);//获取方法修饰符

        Class<?> returnType = method[i].getReturnType();//获取返回值类型
        Class<?> [] para = method[i].getParameterTypes();//获取参数类型
        System.out.print(modifier + " ");
        System.out.print(returnType.getName() + "  ");
        System.out.print(method[i].getName() + " ");
        System.out.print("(");
        for (int j = 0; j < para.length; ++j) {
            System.out.print(para[j].getName() + " " + "arg" + j);
            if (j < para.length - 1) {
                System.out.print(",");
            }
        }
        Class<?> exce[] = method[i].getExceptionTypes();
        if (exce.length > 0) {
            System.out.print(") throws ");
            for (int k = 0; k < exce.length; ++k) {
                System.out.print(exce[k].getName() + " ");
                if (k < exce.length - 1) {
                    System.out.print(",");
                }
            }
        } else {
            System.out.print(")");
        }
        System.out.println();
    }
}

1)clazz.getMethods();//获取本类以及继承类\实现接口的所有public修饰的方法
//执行结果是:
这里写图片描述
可知,里面都是public修饰的方法,private修饰的testtttt()并没有打印出来;

2)clazz.getDeclaredMethods();//只获取本类的所有方法
//执行结果是:
这里写图片描述
本类的所有方法都被获取到了。

7.通过反射机制调用某个类的方法

public void reflect1() {
    System.out.println("Java 反射机制 - 调用某个类的方法1.");
}
public void reflect2(int age, String name) {
    System.out.println("Java 反射机制 - 调用某个类的方法2.");
    System.out.println("age -> " + age + ". name -> " + name);
}
/**
 * 通过反射机制调用某个类的方法
 */
@Test
public void test7() throws Exception{
    Class<?> clazz = Class.forName("test.ReflectTest");
    // 调用TestReflect类中的reflect1方法
    Method method = clazz.getMethod("reflect1");
    method.invoke(clazz.newInstance());
    //output: Java 反射机制 - 调用某个类的方法1.

    // 调用TestReflect的reflect2方法
    method = clazz.getMethod("reflect2", int.class, String.class);
    method.invoke(clazz.newInstance(), 20, "张三");
    // Java 反射机制 - 调用某个类的方法2.
    //output:  age -> 20. name -> 张三
}

8.通过反射机制操作某个类的属性

private String proprety = null;
/**
 * 通过反射机制操作某个类的属性
 */
@Test
public void test8() throws Exception{
    Class<?> clazz = Class.forName("test.ReflectTest");
    Object obj = clazz.newInstance();
    // 可以直接对 private 的属性赋值
    Field field = clazz.getDeclaredField("proprety");
    field.setAccessible(true);
    field.set(obj, "Java反射机制");
    System.out.println("proprety="+field.get(obj));
}

所有源代码的github地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值