转载出处:http://www.cnblogs.com/lzq198754/p/5780331.html
目录
- 反射机制是什么
- 反射机制能做什么
- 反射机制的相关API
- 通过一个对象获得完整的包名和类名
- 实例化Class对象
- 获取一个对象的父类与实现的接口
- 获取某个类中的全部构造函数
- 通过反射机制实例化一个类的对象
- 获取某个类的全部属性
- 获取某个类的全部方法
- 通过反射机制调用某个类的方法
- 通过反射机制操作某个类的属性
- 反射机制的动态代理
- 反射机制的应用实例
- 在泛型为Integer 的ArrayList中存放一个String类型的对象
- 通过反射取得并修改数组的信息
- 通过反射机制修改数组的大小
- 将反射机制应用于工厂模式
反射机制是什么
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射机制能做什么
反射机制主要提供了以下功能:
- 在运行时判断任意一个对象所属的类。
- 在运行时构造任意一个类的对象。
- 在运行时判断任意一个类所具有的成员变量和方法。
- 在运行时调用任意一个对象的方法。
- 生成动态代理。
反射机制的相关API
通过一个对象获得完整的包名和类名
package com.zhihua.reflect;
/**
* 1.通过一个对象获得完整的包名和类名
* @author caizh
*
*/
public class TestReflect_1 {
public static void main(String[] args) {
TestReflect_1 testReflect = new TestReflect_1();
System.out.println(testReflect.getClass().getName());
// 结果 com.zhihua.reflect.TestReflect_1
}
}
实例化Class类对象
package com.zhihua.reflect;
/**
* 2.实例化Class类对象
* 有三种方式
* @author caizh
*
*/
public class TestReflect_2 {
public static void main(String[] args) throws Exception {
Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null;
// 一般采用这种形式
class1 = Class.forName("com.zhihua.reflect.TestReflect_2");
class2 = new TestReflect_2().getClass();
class3 = TestReflect_2.class;
System.out.println("类名称 " + class1.getName());
System.out.println("类名称 " + class2.getName());
System.out.println("类名称 " + class3.getName());
/**
* 0.结果:
* 1.类名称 com.zhihua.reflect.TestReflect_2
* 2.类名称 com.zhihua.reflect.TestReflect_2
* 3.类名称 com.zhihua.reflect.TestReflect_2
*/
}
}
获取一个对象的父类与实现的接口
package com.zhihua.reflect;
import java.io.Serializable;
/**
* 3.获取一个对象的父类与实现的接口
* @author caizh
*
*/
public class TestReflect_3 implements Serializable{
private static final long serialVersionUID = -2862585049955236662L;
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.zhihua.reflect.TestReflect_3");
// 取得父类
Class<?> parentClass = clazz.getSuperclass();
System.out.println("clazz的父类为:"+parentClass.getName());
// clazz的父类为: java.lang.Object
// 获取所有的接口
Class<?> intes[] = clazz.getInterfaces();
System.out.println("clazz实现的接口有:");
for(int i=0;i<intes.length;i++) {
System.out.println((i+1)+": "+intes[i].getName());
}
// clazz 实现的接口有:
/**
* 1: java.io.Serializable
*/
}
}
通过反射机制实例化一个类的对象
package com.zhihua.reflect;
import java.lang.reflect.Constructor;
/**
* 4.获取某个类中的全部构造函数
* @author caizh
*
*/
public class TestReflect_4 {
public static void main(String[] args) throws Exception {
Class<?> class1 = null;
class1 = Class.forName("com.zhihua.reflect.User");
// 第一种方法,实例化默认构造方法,调用set赋值
User user = (User) class1.newInstance();
user.setAge(20);
user.setName("Rollen");
System.out.println(user);
// 结果 User [age=20, name=Rollen]
// 第二种方法 取得全部的构造函数 使用构造函数赋值
Constructor<?>[] constructors =class1.getConstructors();
// 查看每个构造方法需要的参数
for(int i=0;i<constructors.length;i++) {
// 获取参数
Class<?> clazzs[] = constructors[i].getParameterTypes();
System.out.print("cons[" + i + "] (");
for(int j=0;j<clazzs.length;j++) {
if(j==clazzs.length-1){
System.out.print(clazzs[j].getName());
}else {
System.out.print(clazzs[j].getName()+",");
}
}
System.out.println(")");
}
// 结果
/**
* 1.cons[0] (int,java.lang.String)
* 2.cons[1] (java.lang.String)
* 3.cons[2] ()
*/
user = (User) constructors[1].newInstance("Rollen");
System.out.println(user);
// 结果 User [age=0, name=Rollen]
user = (User) constructors[0].newInstance(20,"Rollen");
System.out.println(user);
// 结果 User [age=20, name=Rollen]
}
}
class User {
private int age;
private String name;
public User() {
super();
}
public User(String name) {
super();
this.name = name;
}
public User(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [age=" + age + ", name=" + name + "]";
}
}
获取某个类的全部属性
package com.zhihua.reflect;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* 5.获取某个类的全部属性
* @author caizh
*
*/
public class TestReflect_5 implements Serializable{
private static final long serialVersionUID = -2862585049955236662L;
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.zhihua.reflect.TestReflect_5");
System.out.println("===============本类属性===============");
// 取得本类的全部属性
Field[] fields = clazz.getDeclaredFields();
for(int i=0;i<fields.length;i++) {
// 权限修饰符
int mo = fields[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = fields[i].getType();
// System.out.println(priv);结果 private static final
System.out.println(priv + " " + type.getName() + " " + fields[i].getName() + ";");
// 结果 private static final long serialVersionUID;
}
System.out.println("==========实现的接口或者父类的属性==========");
// 取得实现的接口或者父类的属性
Field[] fields2 = clazz.getFields();
for(int j=0;j<fields2.length;j++) {
// 权限修饰符
int mo = fields2[j].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = fields2[j].getType();
System.out.println(priv + " " + type.getName() + " " + fields2[j].getName() + ";");
}
}
}
获取某个类的全部方法
package com.zhihua.reflect;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 6.获取某个类的全部方法
* @author caizh
*
*/
public class TestReflect_6 implements Serializable {
private static final long serialVersionUID = -2862585049955236662L;
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.zhihua.reflect.TestReflect_6");
Method[] methods = clazz.getMethods();
for(int i=0;i<methods.length;i++) {
Class<?> returnType = methods[i].getReturnType();
Class<?>[] para = methods[i].getParameterTypes();
int temp = methods[i].getModifiers();
System.out.print(Modifier.toString(temp) + " ");
System.out.print(returnType.getName() + " ");
System.out.print(methods[i].getName() + " ");
System.out.print("(");
for(int j=0;j<para.length;j++) {
System.out.print(para[j].getName()+" "+"arg"+j);
if(j<para.length-1) {
System.out.print(",");
}
}
// 返回 方法异常类型
Class<?>[] exce = methods[i].getExceptionTypes();
if(exce.length>0) {
System.out.print(") throws ");
for(int k=0;k<exce.length;k++) {
System.out.print(exce[k].getName()+ " ");
if(k<exce.length-1) {
System.out.print(",");
}
}
}else {
System.out.print(")");
}
System.out.println();
}
}
}
通过反射机制调用某个类的方法
package com.zhihua.reflect;
import java.lang.reflect.Method;
/**
* 7.通过反射机制调用某个类的方法
* @author caizh
*
*/
public class TestReflect_7 {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.zhihua.reflect.TestReflect_7");
// 调用TestReflect_7的 reflect1方法
Method method = clazz.getMethod("reflect1");
method.invoke(clazz.newInstance());
// Java 反射机制 - 调用某个类的方法1.
// 调用TestReflect的reflect2方法
method = clazz.getMethod("reflect2", int.class,String.class);
method.invoke(clazz.newInstance(), 20,"张三");
// Java 反射机制 - 调用某个类的方法2.
// age -> 20. name -> 张三
}
public void reflect1() {
System.out.println("Java 反射机制 - 调用某个类的方法1.");
}
public void reflect2(int age, String name) {
System.out.println("Java 反射机制 - 调用某个类的方法2.");
System.out.println("age -> " + age + ". name -> " + name);
}
}
通过反射机制操作某个类的属性
package com.zhihua.reflect;
import java.lang.reflect.Field;
/**
* 8.通过反射机制操作某个类的属性
* @author caizh
*
*/
public class TestReflect_8 {
private String property = null;
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.zhihua.reflect.TestReflect_8");
Object object = clazz.newInstance();
// 可以直接对private 的属性赋值
Field field = clazz.getDeclaredField("property");
//打破封装 实际上setAccessible是启用和禁用访问安全检查的开关,
//并不是为true就能访问为false就不能访问
//由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式
//关闭安全检查就可以达到提升反射速度的目的
field.setAccessible(true);
field.set(object, "java 反射机制");
System.out.println(field.get(object));
}
}
getDeclaredFields 和 getFields 的区别
getDeclaredFields()获得某个类的所有申明的字段,即包括public、private和proteced,
但是不包括父类的申明字段。
getFields()获得某个类的所有的公共(public)的字段,包括父类。
反射机制的动态代理
package com.zhihua.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 9.反射机制的动态代理
*
* java 中有三种类类加载器
* 1) Bootsrtap ClassLoader 此加载器采用c++编写,一般开发中很少见。
* 2) Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类
* 3) AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器
*
* 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
* @author caizh
*
*/
public class TestReflect_9 {
public static void main(String[] args) {
MyInvocationHandler demo = new MyInvocationHandler();
Subject subject = (Subject) demo.bind(new RealSubject());
String info = subject.say("Rollen", 20);
System.out.println(info);
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj = null;
public Object bind(Object object) {
this.obj = object;
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object temp = method.invoke(this.obj, args);
return temp;
}
}
// 定义项目接口
interface Subject{
public String say(String name,int age);
}
// 定义真实项目
class RealSubject implements Subject{
@Override
public String say(String name, int age) {
return name + " " + age;
}
}
反射机制的应用实例
在泛型为Integer的ArrayList中存放一个String类型的对象
package com.zhihua.reflect;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* 10.在泛型为Integer的ArrayList中存放一个String类型的对象。
* @author caizh
*
*/
public class TestReflect_10 {
public static void main(String[] args) throws Exception {
ArrayList<Integer> list = new ArrayList<>();
Method method = list.getClass().getMethod("add", Object.class);
method.invoke(list, "Java反射机制实现");
System.out.println(list);
// 结果:[Java反射机制实现]
}
}
通过反射取得并修改数组的信息
package com.zhihua.reflect;
import java.lang.reflect.Array;
/**
* 11.通过反射取得并修改数组的信息
* @author caizh
*
*/
public class TestReflect_11 {
public static void main(String[] args) {
int[] temp = {1,2,3,4,5};
Class<?> demo = temp.getClass().getComponentType();
System.out.println("数组类型:"+demo.getName());
System.out.println("数组长度:"+Array.getLength(temp));
System.out.println("数组的第一个元素:"+Array.get(temp, 0));
Array.set(temp, 0, 100);
System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));
}
}
通过反射机制修改数组的大小
package com.zhihua.reflect;
import java.lang.reflect.Array;
/**
* 12.通过反射机制修改数组的大小
* @author caizh
*
*/
public class TestReflect_12 {
public static void main(String[] args) {
int[] temp = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[] newTemp = (int[]) arrayInc(temp, 15);
print(newTemp);
String[] atr = {"a","b","c"};
String[] str1 = (String[]) arrayInc(atr, 8);
print(str1);
}
// 修改数组的大小
public static Object arrayInc(Object object,int len) {
Class<?> arr = object.getClass().getComponentType();
Object newArr = Array.newInstance(arr, len);
int co = Array.getLength(object);
System.arraycopy(object, 0, newArr, 0, co);
return newArr;
}
// 打印
public static void print(Object object) {
Class<?> class1 = object.getClass();
if(!class1.isArray()) {
return;
}
System.out.println("数组的长度为:"+Array.getLength(object));
for (int i = 0; i < Array.getLength(object); i++) {
System.out.print(Array.get(object, i) + " ");
}
System.out.println();
}
}
将反射机制应用于工厂模式
package com.zhihua.reflect;
/**
* 13.将反射机制应用于工厂模式
* @author caizh
*
* 对于普通的工厂模式当文明在添加一个子类的时候,就需要对应的的修改工厂类。
* 当我们添加很多的子类的是偶,会很麻烦。
* 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。
* 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。
*
*/
public class TestReflect_13 {
public static void main(String[] args) {
Fruit fruit = Factory.getInstance("com.zhihua.reflect.Apple");
if(fruit!=null) {
fruit.eat();
}
}
}
interface Fruit{
public abstract void eat();
}
class Apple implements Fruit{
@Override
public void eat() {
System.out.println("I eat Apple");
}
}
class Orange implements Fruit{
@Override
public void eat() {
System.out.println("Orange");
}
}
class Factory{
public static Fruit getInstance(String className) {
Fruit fruit = null;
try {
fruit = (Fruit) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return fruit;
}
}
总结
Class类提供了四个public方法,用于获取某个类的构造方法。
Constructor getConstructor(Class[] params)
根据构造函数的参数,返回一个具体的具有public属性的构造函数Constructor getConstructors()
返回所有具有public属性的构造函数数组Constructor getDeclaredConstructor(Class[] params)
根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)Constructor getDeclaredConstructors()
返回该类中所有的构造函数数组(不分public和非public属性)
四种获取成员方法的方法
Method getMethod(String name, Class[] params)
根据方法名和参数,返回一个具体的具有public属性的方法Method[] getMethods()
返回所有具有public属性的方法数组Method getDeclaredMethod(String name, Class[] params)
根据方法名和参数,返回一个具体的方法(不分public和非public属性)Method[] getDeclaredMethods()
返回该类中的所有的方法数组(不分public和非public属性)
四种获取成员属性的方法
Field getField(String name)
根据变量名,返回一个具体的具有public属性的成员变量Field[] getFields()
返回具有public属性的成员变量的数组Field getDeclaredField(String name)
根据变量名,返回一个成员变量(不分public和非public属性)Field[] getDelcaredField()
返回所有成员变量组成的数组(不分public和非public属性)