转载:http://blog.csdn.net/qinwu19910928/article/details/9101365?locationNum=6&fps=1
今天给大家介绍下Java反射技术
反射是什么,用最简单的语句来介绍反射就是加载类并解剖类的各个组成部分,稍有java基础的人都知道,java类在内存中是以字节码的形式存在的,而java中有一个Class类表示的正是某个类的字节码对象。大家查阅javaAPI可以发现这个类有个静态方法forName,它可以接收一个字符串作为类名,返回值正是此类名所表示的类的字节码对象,至此我们完成了反射技术中的第一步:加载类,也就是说我们成功的把一个我们指定的类加载到内存并且得到它的字节码对象。
那么在java中,到底有几种加载类得到类的字节码对象的方法呢,上面我们介绍的通过Class类的静态方法forName方法是一种,那还有没有其他的方法呢,下面我们就用代码的方式把加载类的几种方法给大家一一呈现:
- package com.reflection;
-
- public class ReflectionDemo {
-
-
-
-
- public static void main(String[] args) throws Exception {
-
-
- Class personClass1 = Class.forName("com.reflection.Person");
-
-
- Class personClass2 = new Person().getClass();
-
-
- Class personClass3 = Person.class;
-
-
- }
-
- }
加载类只是反射技术的第一步,其实反射技术的核心是在第二步,那就是解剖类的各个组成部分,大家想一想,java类有几个组成部分呢,无非就是构造函数、字段和方法,所以,所谓的解剖类的各个组成部分,无非就是解剖出类的构造函数、字段或者是方法。下面我们就一一介绍怎样解剖出的类的这三个部分。
解剖类的构造方法
构造方法在java类中是一种特殊的方法,它的作用只有一个,就是用来创造对象,同样,反射机制解剖构造方法的作用也是为了用它创造对象,我们翻阅一下javaAPI的Class类的方法列表,不难发现他就有一个getConstructor方法,它接收一系列可变参数(关于java可变参数,不熟悉的读者可以先去掌握这部分知识),返回的是一个Constructor对象,里面封装的是一个构造函数,而Constructor对象有一个方法newInstance,同样接收一系类可变参数,返回值是Object类型,此Object类型即是我们反利用解剖出的构造方法创建的新对象。getConstructor只能解剖类的public类型的构造函数,对于private类型的构造函数,需要用到Class类的另外一个函数getDeclaredConstructor,接收的参数和返回值和getConstructor一样,接下来,我们就用代码演示下怎么解剖类的各种构造函数。
被反射的类Person,为了演示解剖各种构造函数,我们给Person添加三个构造函数:
- package com.reflection;
-
- public class Person {
-
- public Person() {
- System.out.println("name");
- }
-
- public Person(String name) {
- System.out.println(name);
- }
-
- private Person(String name, int age) {
- System.out.println(name + age);
- }
-
- }
测试类:演示了如何解剖出类的各种构造函数
- package com.reflection;
-
- import java.lang.reflect.Constructor;
-
- import org.junit.Test;
-
- public class ReflectionDemo {
- @Test
- public void Test1() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
-
- Constructor constructor = PersonClass.getConstructor(null);
-
- Person person = (Person)constructor.newInstance(null);
-
- }
-
- @Test
- public void Test2() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
-
- Constructor constructor = PersonClass.getConstructor(String.class);
-
- Person person = (Person)constructor.newInstance("person name");
-
- }
-
- @Test
- public void Test3() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
-
- Constructor constructor = PersonClass.getDeclaredConstructor(String.class,int.class);
-
- constructor.setAccessible(true);
-
- Person person = (Person)constructor.newInstance("person name",23);
-
- }
- }
解剖类的方法
掌握了怎么反射类的构造方法,再来反射类的方法就很简单了,其实都差不多,下面就直接上代码了
首先给Person类加几个各种各样的方法
- package com.reflection;
-
- public class Person {
-
- public Person() {
- System.out.println("person");
- }
-
- public Person(String name) {
- System.out.println(name);
- }
-
- private Person(String name, int age) {
- System.out.println(name + age);
- }
-
- public void grow() {
- System.out.println("growing......");
- }
-
- public void grow(String name) {
- System.out.println(name + "is growing......");
- }
-
- public int howOld() {
- return 23;
- }
-
- private void sex() {
- System.out.println("I am a boy");
- }
-
- public static void sport() {
- System.out.println("I like run");
- }
- }
测试类:反射Person类中各种各样的方法
- package com.reflection;
-
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Method;
- import org.junit.Test;
-
-
-
- public class ReflectionDemo1 {
-
- Person person = new Person();
-
- @Test
- public void Test1() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
-
- Method method = PersonClass.getMethod("grow", null);
-
- method.invoke(person, null);
- }
-
- @Test
- public void Test2() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
- Method method = PersonClass.getMethod("grow", String.class);
- method.invoke(person, "xiaohei");
-
- }
-
- @Test
- public void Test3() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
- Method method = PersonClass.getMethod("howOld", null);
-
- int age = (Integer)method.invoke(person, null);
- System.out.println(age);
-
- }
-
- @Test
- public void Test4() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
- Method method = PersonClass.getDeclaredMethod("sex", null);
- method.setAccessible(true);
- method.invoke(person, null);
-
- }
-
- @Test
- public void Test5() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
- Method method = PersonClass.getDeclaredMethod("sport", null);
- method.setAccessible(true);
-
- method.invoke(null, null);
-
- }
- }
其实在方法的反射上,有一个方法的反射和其他方法是不大一样的,那就是main方法,到底有什么不一样,大家可以自己去网上查查,这里不赘述。
解剖类的字段
和反射方法差不多,只是Field类有自己独特的方法,直接上代码
给Person类加了几个字段
- package com.reflection;
-
- public class Person {
-
- public String name = "xiaohei";
- private int age = 23;
- private static String sex = "male";
-
- public Person() {
- System.out.println("person");
- }
-
- public Person(String name) {
- System.out.println(name);
- }
-
- private Person(String name, int age) {
- System.out.println(name + age);
- }
-
- public void grow() {
- System.out.println("growing......");
- }
-
- public void grow(String name) {
- System.out.println(name + "is growing......");
- }
-
- public int howOld() {
- return 23;
- }
-
- private void sex() {
- System.out.println("I am a boy");
- }
-
- public static void sport() {
- System.out.println("I like run");
- }
- }
测试类:演示反射各种各样的字段
- package com.reflection;
-
- import java.lang.reflect.Field;
- import org.junit.Test;
-
-
-
-
-
- public class ReflectionDemo2 {
-
- Person person = new Person();
-
- @Test
- public void Test1() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
- Field field = PersonClass.getField("name");
-
- String name = (String)field.get(person);
- System.out.println(name);
-
- field.set(person, "xiaobai");
- }
-
- @Test
- public void Test2() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
- Field field = PersonClass.getDeclaredField("age");
-
- field.setAccessible(true);
- int age = (Integer)field.get(person);
- System.out.println(age);
- field.set(person, 20);
- }
-
- @Test
- public void Test3() throws Exception {
- Class PersonClass = Class.forName("com.reflection.Person");
- Field field = PersonClass.getDeclaredField("sex");
- field.setAccessible(true);
-
- String sex = (String)field.get(person);
- System.out.println(sex);
- field.set(person, "female");
- }
-
- }
以上就是java反射技术的全部内容了,最后跟大家说一下,java反射技术只有在学习框架的时候有用,平实我们编程很少会用到反射技术,因为我们一般都是用new来加载类的,但是反射技术却是各种各样的框架都能用到的核心技术,因为框架都是通过读配置文件来决定加载哪些类的,所有如果想学透框架的核心原理,java反射技术是必须掌握的技术。
好了,不罗嗦了,希望以上内容能对大家的java学习有所帮助