Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。
反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。
Java的反射机制它知道类的基本结构,这种对Java类结构探知的能力,称为Java类的“自审”。
Class类
要正确使用Java反射机制就得使用java.lang.Class这个类。它是Java反射机制的起源。当一个类被加载以后,Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。
反射API
反射API用于反应在当前Java虚拟机中的类、接口或者对象信息
功能
[1] 获取一个对象的类信息.
[2]获取一个类的访问修饰符、成员、方法、构造方法以及超类的信息.
[3]检获属于一个接口的常量和方法声明.
[4]创建一个直到程序运行期间才知道名字的类的实例.
[5] 获取并设置一个对象的成员,甚至这个成员的名字是在程序运行期间才知道.
[6] 检测一个在运行期间才知道名字的对象的方法
使用反射机制的步骤:
- 导入java.lang.relfect 包
- 遵循三个步骤
第一步是获得你想操作的类的 java.lang.Class 对象
第二步是调用诸如 getDeclaredMethods 的方法
第三步使用 反射API 来操作这些信息
获取Class对象的三种方式:
加载XX.class文件进内存时就被封装成了对象,该对象就是字节码文件对象。如何获取Class对象呢?
方式一:
通过对象的getClass方法进行获取。
如:Class clazz=new Person().getClass();//Person是一个类名
麻烦之处:每次都需要具体的类和该类的对象,以及调用getClass方法。
方式二:
任何数据类型都具备着一个静态的属性class,这个属性直接获取到该类型的对应Class对象。
如:Class clazz=Person.class;//Person是一个类名
比第一种较为简单,不用创建对象,不用调用getClass方法,但是还是要使用具体的类,和该类中的一个静态属性class完成。
方式三:
这种方式较为简单,只要知道类的名称即可。不需要使用该类,也不需要去调用具体的属性和行为。就可以获取到Class对象了。
如:Class clazz=Class.forName("包名.Person");//Person是一个类名
这种方式仅知道类名就可以获取到该类字节码对象的方式,更有利于扩展。
以下是一个反射小练习:
1 package com.itheima.test; 2 3 import java.lang.reflect.Constructor; 4 class Test { 5 6 } 7 public class Demo5 { 8 public static void main(String[] args) throws Exception{ 9 /*通过对象取得包名和类名*/ 10 Test t = new Test(); 11 System.out.println(t.getClass()); 12 System.out.println(t.getClass().getName()); 13 14 /*Class类的实例化*/ 15 //方式一: 16 Class<? extends Test> c1 = t.getClass(); 17 System.out.println(c1); 18 19 //方式二: 20 //为了避免特殊性,这里不用Test类,而用java库中的String类 21 Class<String> c2 = String.class; 22 System.out.println(c2); 23 24 //方式三: 25 //forName()方法会抛出异常 26 Class<?> c3 = null; 27 try { 28 c3 = Class.forName("Test"); 29 } catch (ClassNotFoundException e) { 30 e.printStackTrace(); 31 } 32 System.out.println(c3); 33 34 /*Class类的无参构造对象*/ 35 //实例化Class对象,forName()方法会抛异常 36 Class<?> c = null; 37 try { 38 //这里需要完整的包名和类名 39 c = Class.forName("java.lang.String"); 40 } catch (ClassNotFoundException e) { 41 e.printStackTrace(); 42 } 43 44 //生成一个字符串的引用 45 String s = null; 46 try { 47 //将构造好的对象向下转型为String类 48 //newInstance()方法会抛异常 49 s = (String) c.newInstance(); 50 } catch (InstantiationException e) { 51 e.printStackTrace(); 52 } catch (IllegalAccessException e) { 53 e.printStackTrace(); 54 } 55 System.out.println("字符串长度: " + s.length()); 56 /*Class类的有参构造对象*/ 57 58 Class<?> cc = null; 59 try { 60 cc = Class.forName("java.lang.String"); 61 } catch (ClassNotFoundException e) { 62 e.printStackTrace(); 63 } 64 char[] ch = {'h','e','i','m','a'}; 65 String ss = null; 66 //获得Class类对象的有参构造方法,括号里面参数的写法是:类型.class 67 Constructor<?> con = cc.getConstructor(char[].class); 68 //用此构造方法构造一个新的字符串对象,参数为一个char数组 69 ss = (String) con.newInstance(ch); 70 System.out.println("构造的字符串:" + ss); //获得构造的字符串:heima 71 72 } 73 }