您的位置:首页 > 编程语言 > Java开发

java的反射

2015-08-06 14:49 573 查看
java反射

先看一下定义:主要指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

有点绕,解释一下,就是在程序中,我们不需要用new来创建一个对象,而是通过类的父类Class来获取,这样做的好处就是使程序更加灵活,在设计模式中有很大的用处。

一、Class类

我们在面向对象编程中,可以认为万事万物皆对象(就是基本数据类型——java中也有封装的基本数据类型类)。

我们平时编写的类也是一个对象,类是java.lang.Class类的实例对象。可以认为:

There is a class named Class。

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

首先,假设这有一个类class Foo{}

实例化一下 Foo foo1=new Foo();

任何一个类都有一个隐含的静态成员变量class

Class c1=Foo.class;

已知该类的对象通过getClass方法

Class c2=foo1.getClass();

官网上说c1,c2是Foo类的类类型。万事万物皆对象,类也是对象,是Class类的实例对象,这个对象我们称为该类的类类型。

注意:一个类只可能是CLass类的一个实例,也就是c1==c2.

使用Class.forName()

Class c3=Class.forName(“com.example.foo”);

我们可以通过类的类类型来创建该类的实例对象。

Foo foo2=(Foo)c1.newInstance();

该类必须有一个无参的构造函数,才能使用newInstance();

类的两种加载方式:

1. 静态加载:

new 创建对象是静态加载类,在编译时刻加载所有可能用到的类。

2. 动态加载

功能性的类,加载时最好使用动态加载。在运行时加载,使用接口编程。

二、方法的反射

[code]/**
     * 获取成员函数信息
     * @param obj 该对象所属类的信息
     */
    public static void printClassMethods(Object obj){
        //要获取类的信息  首先要获取类的类类型
        Class c1=obj.getClass();//传递的是哪个子类的对象  c1就是该子类的类类型
        //获取类的名称
        System.out.println("类的名称是:"+c1.getName());
        /*
         * Method类,方法对象
         * 一个成员方法就是一个Method对象
         * getMethods()方法获取的是所有的public的函数,包括父类继承而来的
         * getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
         */
        Method[] ms=c1.getMethods();
        //c1.getDeclaredMethods();
        for (Method method : ms) {
            //得到方法的返回值类型的类类型
            Class returnType=method.getReturnType();
            System.out.print(returnType.getSimpleName()+" ");
            //得到方法的名称
            System.out.print(method.getName()+"(");
            //获取参数类型--->得到的是参数列表的类型的类类型
            Class[] paramType=method.getParameterTypes();
            for (Class class1 : paramType) {
                System.out.print(class1.getSimpleName()+",");
            }
            System.out.println(")");
        }
    }


三、成员变量的反射

[code]/**
     * 获取成员变量的信息
     * @param obj
     */
    public static void printClassField(Object obj){
        Class c=obj.getClass();
        /*
         * 成员变量也是对象
         * java.lang.reflect.Field 封装了关于成员变量的操作
         * getFields()方法获取的是所有的public的成员变量的信息
         * getDeclaredFields获取的是该类自己声明的成员变量的信息
         */
        //Field[] fs = c.getFields();
        Field[] fs=c.getDeclaredFields();
        for (Field field : fs) {
            //得到成员变量的类型的类类型
            Class fieldType=field.getType();
            //得到成员变量的名称--->field.getName()
            System.out.println(fieldType.getSimpleName()+" "+field.getName());
        }
    }


四、构造函数的反射

[code]/**
     * 获取构造函数的信息
     * @param obj
     */
    public static void printClassConstructor(Object obj){
        Class c=obj.getClass();
        /*
         * 构造函数也是对象
         * java.lang. Constructor中封装了构造函数的信息
         * getConstructors获取所有的public的构造函数
         * getDeclaredConstructors得到所有的构造函数
         */
//      Constructor[] cons=c.getConstructors();
        Constructor[] cons=c.getDeclaredConstructors();
        for (Constructor constructor : cons) {
            //获取构造函数的参数列表--->得到的是参数列表的类类型
            Class[] paramType=constructor.getParameterTypes();
            System.out.print(constructor.getName()+"(");
            for (Class class1 : paramType) {
                System.out.print(class1.getSimpleName()+",");
            }
            System.out.println(")");
        }
    }


测试方法:

[code]public class TestDemo {

    public static void main(String[] args) {
        String str="hello";
        ClassUtils.printClassMethods(str);
        ClassUtils.printClassField(str);
        ClassUtils.printClassConstructor(str);
        }
}


测试结果:

[code]类的名称是:java.lang.String
boolean equals(Object,)
……
java.lang.String(StringBuffer,)
java.lang.String(int,int,char[],)


五、方法的反射操作

method.invoke(对象,参数列表)

[code]package com.example.young;

import java.lang.reflect.Method;

public class TestDemo {

    public static void main(String[] args) {
/*      String str="hello";
        ClassUtils.printClassField(str);
        ClassUtils.printClassMethods(str);
        ClassUtils.printClassConstructor(str);
        */
        //通过反射操作类的方法

        A a1 = new A();
        //1、获取类的类类型
        Class c=a1.getClass();
        try {
            /*2.获取方法 名称和参数列表决定
            getMethod获取的是public的方法
            getDelcaredMethod自己声明的方法*/
            Method m=c.getMethod("print", int.class ,int.class);
            //方法如果没有返回值返回null,有返回值返回具体的返回值
            Object obj=m.invoke(a1,2,3);

            Method m2=c.getMethod("print", new Class[]{String.class,String.class});
            Object obj1=m2.invoke(a1, "hello"," world");
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
}

class A{
    public void print(){
        System.out.println("hello");
    }

    public void print(int a,int b){
        System.out.println(a+b);
    }

    public void print(String a,String b){
        System.out.println(a+b);
    }
}


测试结果:

[code]5
hello world


学会反射对我们以后的java学习有很大的帮助,能更好的让我们理解当下java的流行框架。现在很多公司用的框架都是自己写的,这时候就要用到反射了。javaweb中的常见框架struts2、hibernate、spring等都用到了反射。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: