一、认识java Reflection反射机制
Java Reflecation的定义
Reflection(反射)被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性和方法。
Java反射机制提供的功能
1、在运行时判断任意一个对象所属的类;
2、在运行时构造任意一个类的对象;
3、在运行时判断任意一个类所具有的成员变量和方法;
4、在运行时调用任意一个对象的成员变量和方法;
5、生成动态代理。
反射相关的API
java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造方法
二、公用类
因为在这里,我们会用到一些类,所以我先贴出来,等着下面举例的时候可以参考:
1、Person类:


package com.xiaop.reflection;
@MyAnnotation(value = "piper")
public class Person extends Creature implements Comparable{
public String name;
private int age;
public int i;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person(String name) {
super();
this.name = name;
}
public Person() {
super();
}
@Override
public int compareTo(Object arg0) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@MyAnnotation(value = "abc123")
public void show(){
System.out.println("我是一个人!");
}
private Integer display(String nation,Integer i) throws Exception{
System.out.println("我的国籍是:" + nation);
return i;
}
public static void info(){
System.out.println("中国人!");
}
class Bird{
}
}
2、Person的父类Creature


package com.xiaop.reflection;
public class Creature<T> {
private double weight;
public String colar;
public void health(){
System.out.println("呼吸");
}
}
3、Person类继承的接口MyInterface


package com.xiaop.reflection;
import java.io.Serializable;
public interface MyInterface extends Serializable {
}
4、Person类用到的注解Annotation


package com.xiaop.reflection;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
}
三、Class类
1、在Object类中定义了以下的方法,此方法将被所有子类继承:
● public final Class getClass()
以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。
2、对照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。
3、Class本身也是一个类
4、Class 对象只能由系统建立对象
5、一个类在 JVM 中只会有一个Class实例
6、一个Class对象对应的是一个加载到JVM中的一个.class文件
7、每个类的实例都会记得自己是由哪个 Class 实例所生成
8、通过Class可以完整地得到一个类中的完整结构
1.Class常用的方法:
方法名 | 功能说明 |
static Class forName(String name) | 返回指定类名 name 的 Class 对象 |
Object newInstance() | 调用缺省构造函数,返回该Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称 |
Class getSuperClass() | 返回当前Class对象的父类的Class对象 |
Class [] getInterfaces() | 获取当前Class对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Class getSuperclass() | 返回表示此Class所表示的实体的超类的Class |
Constructor[] getConstructors() | 返回一个包含某些Constructor对象的数组 |
Field[] getDeclaredFields() | 返回Field对象的一个数组 |
Method getMethod(String name,Class … paramTypes) | 返回一个Method对象,此对象的形参类型为paramType |
例如,有了反射之后,我们可以通过反射创建类的对象,并调用类对象的结构
/**
* 有了反射,可以通过反射创建一个类的对象,并调用其中的结构
* @throws Exception
*/
@Test
public void test2() throws Exception {
Class<Person> clazz = Person.class;
//1.创建clazz对应的运行时类Person类的对象
Person p = (Person) clazz.newInstance();
//2.通过反射调用运行时类的指定的属性
//2.1
Field field = clazz.getDeclaredField("name");
field.set(p, "LiuDeHua");
System.out.println(p);
//2.2
Field fieldAge =clazz.getDeclaredField("age");
fieldAge.setAccessible(true);
fieldAge.set(p, 20);
System.out.println(p);
//3.通过反射调用运行时类的指定的方法
Method m = clazz.getMethod("show");
Object objVal = m.invoke(p);
Method m1 = clazz.getMethod("display", String.class,Integer.class);
Object objVal1 = m1.invoke(p, "zhongguo",30);
System.out.println(objVal1);
}
2.实例化Class类的对象(四种方法)
第一种:若已知具体的类,通过类的class属性获取,该方法最安全可靠,程序性能最高;
例如:Class clazz = String.Class;
第二种,若已知某个类的事例,调用该事例的getClass方法过去Class对象;
例如:Class clazz = "com.xiaop.Person".getClass();
第三种:已知一个类的全类名,且该类在类路径下,可以通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException;
例如:Class clazz = Class.forName("java.lang.String");
第四种:ClassLoader cl = this.getClass().getClassLoader();
Class clazz = cl.loadClass("类的全类名");
代码示例:
/**
* 如何获取Class的实例(3种)
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
@Test
public void test4() throws Exception{
//1.调用运行时类本身的.class属性
Class clazz1 = Person.class;
System.out.println(clazz1.getName());
Class clazz2 = String.class;
System.out.println(clazz2.getName());
//2.通过运行时类的对象获取
Person p = new Person();
Class clazz3 = p.getClass();
System.out.println(clazz3.getName());
//3.通过Class的静态方法获取.通过此方式,体会一下,反射的动态性。
String className = "com.xiaop.reflection.Person";
Class clazz4 = Class.forName(className);
//clazz4.newInstance();
System.out.println(clazz4.getName());
//4.(了解)通过类的加载器
ClassLoader classLoder = this.getClass().getClassLoader();
Class clazz5 = classLoder.loadClass(className);
System.out.println(clazz5.getName());
System.out.println(clazz1 == clazz3);//true
System.out.println(clazz1 == clazz4);//true
System.out.println(clazz1 == clazz5);//true
}