您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
javase第三季学习笔记-反射机制
发布时间:2017-08-10 15:34:27编辑:雪饮阅读()
什么是反射
• 反射: Reflection
Class类
• Class类是一切的反射根源。
• Class类表示什么?
• 很多的人——可以定义一个Person类(有年龄,性别,姓名等)
• 很多的车——可以定义一个Car类(有发动机,颜色,车轮等)
• 很多的类——Class类(类名,构造方法,属性,方法)
• 得到Class类的对象有三种方式:
• 第一种形式:Object类中的getClass()方法
• 第二种形式:类.class
• 第三种形式:通过Class类的forName方法:
• 使用Class类进行对象的实例化操作
• 调用无参构造进行实例化
– public T newInstance() throws InstantiationException,IllegalAccessException
• 调用有参构造进行实例化
– public Constructor<?>[] getConstructors() throws SecurityException
通过Class类取得类信息
n 取得类所在的包
• public Package getPackage() //得到一个类所在的包
• public String getName() //得到名字
n 取得一个类中的全部方法
• public Method[] getMethods()
• public int getModifiers() //Modifier.toString(mod); // 还原修饰符
• public Class<?> getReturnType()
• public Class<?>[] getParameterTypes()
• public Class<?>[] getExceptionTypes()
• public static String toString(int mod)
n 取得一个类中的全部属性
• public Field[] getFields()
• public Field[] getDeclaredFields()
• public Class<?> getType()
• public int getModifiers()
• public String getName()
通过Class类调用属性或方法
n 调用类中的方法
• 调用类中的方法,传入实例化对象,以及具体的参数内容
• public Object invoke(Object obj,Object... args)
n 直接调用属性
• 取得属性
• public Object get(Object obj)
• //设置属性,等同于使用“=”完成操作
• public void set(Object obj,Object value)
• //让属性对外部可见
• public void setAccessible(boolean flag)
示例代码:
主入口:
package com.vince.ref;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class RefDemo {
public static void main(String[] args) throws ClassNotFoundException {
//无论new多少个对象,类加载器对于一个类只会生成一份Class对象
Person p1=new Person("小女",18,'女');
Person p2=new Person("小男",18,'男');
//创建Class对象的方式一
Class personClass1=p1.getClass();
Class personClass2=p2.getClass();
System.out.println(personClass1==personClass2);
//创建Class对象的方式二
Class personClass3=Person.class;
System.out.println(personClass2==personClass3);
//创建Class对象的方式三(该方式会抛出异常)
Class personClass4=Class.forName("com.vince.ref.Person");
System.out.println(personClass3==personClass4);
//通过随便一个Class对象的引用即可获取无参构造方法体
//如果类中没有无参构造方法,将会报异常。
try {
Person p3=(Person)personClass3.newInstance();
System.out.println(p3);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//调用有参构造方法
Constructor[] cs=personClass4.getConstructors();//获取当前类的所有构造方法
for(Constructor c:cs){
//输出方法名称
System.out.println("方法名称:"+c.getName());
System.out.println("参数类型数组:");
Class[] paramsTypes=c.getParameterTypes();
for(Class class1:paramsTypes){
System.out.println(class1);
}
}
//获取指定参数类型的构造方法
Person p4=null;
try {
Constructor c1=personClass4.getConstructor(String.class,int.class,char.class);
p4=(Person)c1.newInstance("小花",17,'女');
System.out.println(p4);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println("----获得类信息-----");
System.out.println("包信息:"+personClass4.getPackage().getName());
System.out.println("类名:"+personClass4.getName());
/*
返回一个包含某些Method对象的数组
这些对象反映此Class对象所表示的类或接口
(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)
的公共member方法
*/
System.out.println("----获取方法Class对象的方法(公共方法)----");
Method[] ms=personClass4.getMethods();
for(int i=0;i<ms.length;i++){
Method m=ms[i];
System.out.println("方法名:"+m.getName());
}
/*
返回Method对象的一个数组,这些对象反映此
Class对象表示的类或接口声明的所有方法
包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
*/
System.out.println("----获取方法Class对象的方法(声明方法)----");
Method[] ms2=personClass4.getDeclaredMethods();
for(int i=0;i<ms2.length;i++){
Method m=ms2[i];
System.out.println("方法名:"+m.getName()+" 该方法的修饰符:"+Modifier.toString(m.getModifiers()));
}
System.out.println("---获取属性信息(公有)---");
Field[] fs=personClass4.getFields();
for(int i=0;i<fs.length;i++){
System.out.println(fs[i].getName());
}
System.out.println("---获取属性信息(私有)---");
Field[] fs2=personClass4.getDeclaredFields();
for(int i=0;i<fs2.length;i++){
System.out.println(fs2[i].getName());
}
System.out.println("---调用方法和属性---");
try {
Method setNameMethod=personClass4.getMethod("setName",String.class);
//调用方法
setNameMethod.invoke(p4,"菲菲");
System.out.println(p4);
//调用私有方法
Method sayMethod=personClass4.getDeclaredMethod("say");
//开启允许访问
sayMethod.setAccessible(true);
//私有方法终于被调用
sayMethod.invoke(p4);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println("----调用属性----");
try {
Field ageField=personClass4.getDeclaredField("age");
ageField.setAccessible(true);
//获取属性值
System.out.println(ageField.get(p4));
//设置属性值
ageField.set(p4,22);
System.out.println(p4);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
用到的类:
package com.vince.ref;
public class Person {
private String name;
private int age;
private char sex;
private void say(){
System.out.println("my name is "+name);
}
public Person() {
super();
System.out.println("Person无参构造方法被调用");
}
public Person(String name, int age, char sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
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 char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
}
动态代理
• 所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联。
• java动态代理主要是使用java.lang.reflect包中的两个类。
n InvocationHandler类
• public Object invoke(Object obj,Method method,Object[] obs)
• 其中第一个参数 obj 指的是代理类,method是被代理的方法,obs是指被代理的方法的参数组。此方法由代理类来实现。
n Proxy类
• protected Proxy(InvocationHandler h);
• static Class getProxyClass(ClassLoader loader,Class[] interfaces);
• static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h);
• 动态代理其实是在运行时生成class,所以,我们必须提供一组interface,然后告诉他class已经实现了这些interface,而且在生成Proxy的时候,必须给他提供一个handler,让他来接管实际的工作。
示例代码:
入口程序:
package com.vince.dynaproxy;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
Person p=new Person("小白");
DynaProxy dynaProxy=new DynaProxy(p);
//Proxy提供用于创建动态代理类和实例的静态方法
//它还是由这些方法创建的所有动态代理类的超类
Subject s=(Subject)Proxy.newProxyInstance(p.getClass().getClassLoader(), p.getClass().getInterfaces(),dynaProxy);
s.miai();
}
}
要代理的主题接口
package com.vince.dynaproxy;
//要代理的主题接口
public interface Subject {
public void miai();//相亲
}
被代理类
package com.vince.dynaproxy;
//被代理类
public class Person implements Subject {
private String name;
public Person(String name){
this.name=name;
}
public void miai() {
System.out.println(name+"正在相亲中。。。");
}
}
动态代理类
package com.vince.dynaproxy;
//动态代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynaProxy implements InvocationHandler {
//被代理对象
private Object target;
public DynaProxy(Object target) {
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object obj=null;
before();
//正在调用业务方法
obj=method.invoke(target, args);
after();
return obj;
}
//相亲之前要做的事情
private void before(){
System.out.println("为代理人匹配如意郎君");
}
//相亲之后要做的事情
private void after(){
System.out.println("本次相亲结束");
}
}
关键字词:javase,反射机制
下一篇:javase第三季学习笔记-泛型