反射的概念
什么是反射:
反射就是通过获取类的字节码文件对象:Class
创建该类的实例(通过构造方法:Constroctor类),调用成员方法(Method类),
给成员变量赋值(Field类)
关于面试题:获取字节码文件的方式有几种
三种方式
1)Object类的getClass():表中正在运行的Java类(当前类字节码文件)
2)任意Java类型的.class属性
3)反射Class类中forName("类或者接口的全限定名称") ;
com.qianfeng.reflect_10.ReflectDemo
1.Java代码经历的三个阶段
SOURCE阶段:源码阶段 javac---java源代码进行编译
CLASS阶段:类的加载以及初始化阶段 ----xxx.class文件 (检查类的语法结构)
运行阶段:输入 java 类名------ 产生结果...
2.如何获取一个类的Constructor并创建该类实例呢?
1)先获取当前类的Class对象(字节码文件对象)
Class clazz = Class.forName("类的全限定名称") ;
2)如果当前构造方法公共的: Constructor<T> getConstructor()
如果当前公祖方法私有/默认/受保护的: Constructor<T> getDeclaredConstructor()
3)通过构造器创建该类实例
Constructor类 public Object newInstance() ;
3.如何获取一个类Method并调用该方法呢?
1)先获取当前类的Class对象(字节码文件对象)
Class clazz = Class.forName("类的全限定名称") ;
方式1:直接通过当前字节码文件对象创建该类实例
Object obj = clazz.newIntance() ;
方式2:通过构造方法创建该类实例
Constructor<T> getConstructor()
public Object newInstance() ;
2)获取Method并调用
如果当前成员方法是公共的: Method<T> getMethod(String name,Class<T>...paramerters)
果当前成员方法是私有的/受保护的/默认的修饰符:Method<T> getDeclaredMethod()
Method m = clazzz.getMethod("方法名称") ;
3)调用方法
m.invoke(obj) ;
4.如何读取src目录下面的xxx.properties文件?
1)获取当前类的字节码文件对象同时获取该类的类加载器对象ClassLoader
2)InputStream in = getResourceAsStream("src目录下配置文件") ;
InutStream inputStream = 类名.class.getClassLoader().getResourceAsStream("src目录下配置文件") ;
创建属性集合类
Properties prop = new Properties() ;
prop.load(inputStream) ;
5.获取Field并使用
Class clazz= Class.forName("类的全限定名称") ;
Constructor con = clazz.getConstructor();
Object obj = con.newInstance() ;
Field field = clazz.getField("字段名称") ;
file.set(obj,实际的值) ;
使用反射获取构造方法并使用
之前的写法:
Person p = new Person();通过无参构造方法创建对象
Person p = new Person("高圆圆"); 形参String---String类型字节码文件格式
java.lang.String
使用反射获取构造方法并使用,(Constructor)
Class 类的实例表示正在运行的 Java 应用程序中的类和接口
1.获取Person类的字节码文件对象
例:Class c = Class.forName("com.qianfeng.reflect_01.Person") ;
2.获取构造方法(构造器)对象
表示获取当前类中的所有的公共的构造方法
获取当前类中所有的构造方法:包括私有的,公共的,默认,受保护的(proteted)
例:
Constructor[] cons = c.getConstructors() ;
for(Constructor con: cons) {
System.out.println(con);
3.获取某一个构造方法所在对象:Constructor
获取指定的公共构造方法
参数是当前的字节码文件Class
例:
Person p = new Person();通过无参构造方法创建对象
直接输出p----->如果重写toString():成员信息的表达式
Constructor con = c.getConstructor() ;
4.通过构造器如何获取当前Person类的实例
例:
Object obj = con.newInstance() ;
System.out.println(obj);
创建该类的实例(Constroctor类)
之前的写法:
Person p = new Person("高圆圆") ;
System.out.println(p) ; toString()
public class ReflectDemo {
public static void main(String[] args) throws Exception{
Class c = Class.forName("com.qianfeng.reflect_01.Person") ;
Constructor con = c.getConstructor(String.class,int.class,String.class) ;
con.setAccessible(true);
Object obj = con.newInstance("高圆圆",27,"西安市鄠邑区") ;
System.out.println(obj);
调用成员方法(Method类)
之前的写法:
通过无参构造方法创建对象
Person p = new Pereson() ;
p.show();
使用反射获取Person类的字节码文件对象,并获取成员方法Method并使用
@SuppressWarnings("all")
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
Class c = Class.forName("com.qianfeng.reflect_01.Person") ;
Constructor con = c.getConstructor() ;
Object obj = con.newInstance() ;
Method m = c.getMethod("show") ;
m.invoke(obj) ;
例:使用方法method和function方法
Method m2 = c.getMethod("method", int.class) ;
Object object = m2.invoke(obj, 100) ;
System.out.println(object);
System.out.println("-------------------------------------");
Method m3 = c.getDeclaredMethod("function", String.class) ;
m3.setAccessible(true);
m3.invoke(obj, "hello,张佳宁") ;
给成员变量赋值(Field类)
之前的写法:
Person p = new Person() ;
p.字段名(属性名) = "赋值";
通过反射获取成员变量Field并使用
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
Class c = Class.forName("com.qianfeng.reflect_01.Person") ;
Constructor con = c.getConstructor() ;
Object obj = con.newInstance() ;
Field field = c.getDeclaredField("name") ;
field.setAccessible(true);
field.set(obj, "高圆圆");
System.out.println(obj);
反射的应用
利用Class.forName("类的全限定名") ;将类的全限定名放置在配置文件中
* xx.txt 文本文件
* xx.properties文件
@SuppressWarnings("all")
public class Test {
public static void main(String[] args) throws Exception {
Student s = new Student() ;
s.love();
System.out.println("-------------------");
Worker w = new Worker() ;
w.love();
System.out.println("--------------------------------");
Properties prop = new Properties() ;
Reader r = new FileReader("class.txt") ;
prop.load(r);
r.close();
System.out.println(prop);
String className = prop.getProperty("className") ;
String methodName = prop.getProperty("methondName") ;
Class clazz = Class.forName(className) ;
Object obj = clazz.newInstance() ;
Method m = clazz.getMethod("love") ;
m.invoke(obj) ;
}
}
如何读取src目录下的properties配置文件
public class Test2 {
public static void main(String[] args) throws Exception {
ClassLoader classLoader = Test2.class.getClassLoader() ;
InputStream inputStream = classLoader.getResourceAsStream("class.properties") ;
Properties prop = new Properties() ;
prop.load(inputStream);
String className = prop.getProperty("className") ;
String methodName = prop.getProperty("methondName") ;
Class c = Class.forName(className) ;
Object obj = c.newInstance() ;
Method m = c.getMethod(methodName) ;
m.invoke(obj) ;
}
}
反射的应用2
需求:
有一个ArrayList<Integer>集合,需要给里面添加String类型的数据,如何实现呢?
public class Test3 {
public static void main(String[] args) throws Exception{
ArrayList<Integer> array = new ArrayList<Integer>() ;
array.add(100) ;
array.add(200) ;
Class clazz = array.getClass() ;
Method m = clazz.getMethod("add", Object.class) ;
m.invoke(array, "hello") ;
m.invoke(array, "world") ;
System.out.println(array);
}
}
代理模式
设计模式:
结构型设计模式:
代理模式
静态代理
动态代理
jdk动态代理
CGlib动态代理
静态代理:--------Thread 的实现方式2 implements Runnable接口
真实角色:专注于自己的功能
代理角色:帮助真实角色对实际的方法进行增强
都需要实现指定的接口'
动态代理:在程序的运行过程中产生的代理类
JDK动态代理
Proxy 提供用于创建动态代理类和实例的静态方法
静态方法:
public static Object newProxyInstance
(
ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h
)
参数1:表示类的加载器
参数2:获取类的接口列表的Class字节码文件
参数3:代理实例的处理程序 接口:InvocationHandler
JDK动态代理:在程序运行过程中,通过反射的产生的代理类(Proxy以及它里面代理的处理程序:InvocationHandler)