java夯实基础系列:反射

一.反射定义&通俗理解

  反射之中包含了一个“反”的概念,所以要想解释反射就必须先从“正”开始解释,一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产生实例化对象,但是“反”指的是通过对象找到类。
  反射提供了一种运行期获取对象元信息的手段。写框架代码用的比较多,因为需要运行时动态获取和操作对象的属性和方法。尽量少用反射,会有性能开销,大多数场景下可以用设计模式代替。即:根据类的信息来加载这个类,然后构造这个对象,然后再调用这个类中的属性和方法。

二.反射好处,是为了解决什么问题存在的呢?

Java反射的作用:
  在Java运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法。对于任意一个对象,可以调用它的任意一个方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。
Java 反射机制主要提供了以下功能

  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时调用任意一个对象的方法

三.反射涉及的类库在java包里在哪里,都有哪些方法呢

Java的反射机制的实现要借助于4个类:class,Constructor,Field,Method;
其中class代表的时类对象,
Constructor-类的构造器对象,
Field-类的属性对象,
Method-类的方法对象。
通过这四个对象我们可以粗略的看到一个类的各个组 成部分。

1.Class

  其中最核心的就是Class类,它是实现反射的基础,它包含的方法我们在第一部分已经进行了基本的阐述。应用反射时我们最关心的一般是一个类的构造器、属性和方法。

java中主要是通过四种方式来进行class的加载的:
1.classLoader
2.类名.class.
3.对象名.getClass()
4.Class.forName();
我个人觉得1、4是比较常用的,因为这两个可以通过类的信息找到类,进而将类加载的JVM中。你只需传递给他们字符串就ok。

获取Class对象的方式:

方式一:通过Object类的getClass()方法取得,基本不用:

packagecn.mldn.demo;
classPerson {}
publicclassTestDemo {
publicstaticvoidmain(String[] args) throwsException {
Person per = newPerson() ; // 正着操作
Class<?> cls = per.getClass() ; // 取得Class对象
System.out.println(cls.getName()); // 反着来
}
}

方式二:使用“类.class”取得,在日后学习Hibernate开发的时候使用

packagecn.mldn.demo;
classPerson {}
publicclassTestDemo {
publicstaticvoidmain(String[] args) throwsException {
Class<?> cls = Person.class; // 取得Class对象
System.out.println(cls.getName()); // 反着来
}
}

方式三:使用Class类内部定义的一个static方法,主要使用取得Class类对象:public static Class

forName(String className) throws ClassNotFoundException;
packagecn.mldn.demo;
classPerson {}
publicclassTestDemo {
publicstaticvoidmain(String[] args) throwsException {
Class<?> cls = Class.forName("cn.mldn.demo.Person") ; // 取得Class对象
System.out.println(cls.getName()); // 反着来
}
}
通过Class对象获取实例化对象

范例:通过反射实例化对象

packagecn.mldn.demo;
classPerson {
@Override
publicString toString() {
return"Person Class Instance .";
}
}
publicclassTestDemo {
publicstaticvoidmain(String[] args) throwsException {
Class<?> cls = Class.forName("cn.mldn.demo.Person") ; // 取得Class对象
Object obj = cls.newInstance() ; // 实例化对象,和使用关键字new一样
Person per = (Person) obj ; // 向下转型
System.out.println(per);
}
}

  那么现在可以发现,对于对象的实例化操作,除了使用关键字new之外又多了一个反射机制操作,而且这个操作要比之前使用的new复杂一些,可是有什么用?
  对于程序的开发模式之前一直强调:尽量减少耦合,而减少耦合的最好做法是使用接口,但是就算使用了接口也逃不出关键字new,所以实际上new是造成耦合的关键元凶。

  以上只是利用了Class类作为了反射实例化对象的基本应用,但是对于一个实例化对象而言,它需要调用类之中的构造方法、普通方法、属性,而这些操作都可以通过反射机制完成。

2.Constructor

得到构造器的方法
Constructor getConstructor(Class[] params) – 获得使用特殊的参数类型的公共构造函数,

Constructor[] getConstructors() – 获得类的所有公共构造函数

Constructor getDeclaredConstructor(Class[] params) – 获得使用特定参数类型的构造函数(与接入级别无关)

Constructor[] getDeclaredConstructors() – 获得类的所有构造函数(与接入级别无关)

3.Field

获得字段信息的方法
Field getField(String name)
Field[] getFields()
Field getDeclaredField(String name)

Field[] getDeclaredFields()

4.Method

获得方法信息的方法
Method getMethod(String name, Class[] params) – 使用特定的参数类型,获得命名的公共方法

Method[] getMethods() – 获得类的所有公共方法

Method getDeclaredMethod(String name, Class[] params) – 使用特写的参数类型,获得类声明的命名的方法

Method[] getDeclaredMethods() – 获得类声明的所有方法

四.我写的一个小demo:

/**
 * Created by annuoaichengzhang on 16/4/14.
 */

class Person {
    private String name;
    private String age;

    public Person() {
    }

    public Person(String name, String age) {

    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}


public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        // 正者操作
        Person person = new Person();

        Class<? extends Person> personClass = person.getClass();
        System.out.println(personClass.getName());
        // 输出结果:reflect.Person

        Class<Person> personClass1 = Person.class;
        System.out.println(personClass1.getName());
        // 输出结果:reflect.Person

        Class<?> aClass = Class.forName("reflect.Person");
        Object object = aClass.newInstance();
        Person person1 = (Person) object;

        System.out.println(person1);


        // 构造函数相关
        Constructor<?> constructor = aClass.getConstructor(String.class, String.class);
        Object object3 = constructor.newInstance("张三", "20");
        System.out.println(object3);


        // 全部属性
        Field[] fields = aClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            System.out.println(fields[i]);
        }

        Field name = aClass.getDeclaredField("name");
        name.setAccessible(true);
        name.set(object3, "张三");
        System.out.println(name.get(object3));


        // 方法
        Method[] methods = aClass.getMethods();
        for (int i = 0; i < methods.length; i++) {
            System.out.println(methods[i]);
        }

        Method setName = aClass.getMethod("setName", String.class);
        Method getName = aClass.getMethod("getName");
        setName.invoke(object3, "张四");
        System.out.println(getName.invoke(object3));




    }


}


更多资料:
http://a.codekk.com/detail/Android/Mr.Simple/%E5%85%AC%E5%85%B1%E6%8A%80%E6%9C%AF%E7%82%B9%E4%B9%8B%20Java%20%E5%8F%8D%E5%B0%84%20Reflection

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值