一:反射
1. java.lang.class
类加载过程:
程序经过javac.exe命令后,会生成一个或多个字节码文件(.class结尾)
再使用java.exe对某个字节码文件解释运行,就相当于把字节码文件加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的Class对象。(类加载器作用)
加载到内存中的类成为运行时类,运行时类是Class的一个实例。
初始化:
类构造器(构造类信息的)方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。
当初始化类是,父类还没初始化则先初始化父类。
可以有Class对象:
类、接口、数组、枚举、注解、基本数据类型、void
2.获取运行时类的方式
方式一:类名.class
方式二:类对象名.getClass( )
方式三:Class.forName("java.lang.String") //以String为例
3.通过运行时类造对象,获取类的结构
clazz.newInstance( ):必须提供空参构造器,且权限为public
(1).属性
getFields( ):只有public的属性,包含运行时类及其父类的属性
getDeclaredFileds( ):所有权限的属性,但只有运行时类的
(2).方法
getMethods( ):只有public的方法,包含运行时类及其父类的方法
getDeclaredMethods( ):所有权限的方法,但只有运行时类的
(3).其他
getSuperclass( )
getInterface( )
getAnnotations( )
(4).带泛型的父类的泛型
Type gSuperclass = clazz.getGenericSuperClass( ) //带泛型的父类
ParameterizedType paramType =(ParameterizedType) genericSuperClass;
Type[ ] actualTypeArguments = paramType.getActualTypeArguments( );//获取泛型类型
4.设置属性
Person p=(Person) class.newInstance( );//创建运行时类的对象
Field name = clazz.getDeclaredField( "name" ); //获取指定变量名对应的属性
name.setAccessible(true);//设置属性可被访问
name.set(p,"Tom"); //
name.get(p) //
5.调用方法
method.invoke(p,args...) //p为运行时类的对象,args为给方法形参赋值的实参
二:动态代理
1.静态代理
interface ClothFactory{
void produceCloth();
}
//代理类
class ProxyClothFactory implements ClothFactory{
private ClothFactory factory;//拿被代理类对象进行实例化
public ProxyClothFactory(ClothFactory factory){
this.factory=factory;
}
@Override
public void produceCloth() {
System.out.println("代理工厂做一些准备工作");
factory.produceCloth();
System.out.println("代理工厂做一些后续收尾工作");
}
}
//被代理类
class NikeClothFactory implements ClothFactory{
@Override
public void produceCloth() {
System.out.println("nike");
}
}
public class pra06 {
public static void main(String[] args) {
NikeClothFactory nike = new NikeClothFactory();//被代理类对象
ProxyClothFactory proxyNike = new ProxyClothFactory(nike);//代理类对象
proxyNike.produceCloth();
}
}
2.动态代理
interface Human{
String getBelief();
void eat(String food);
}
class SuperMan implements Human{//被代理类
@Override
public String getBelief() {
return "i believe i can fly";
}
@Override
public void eat(String food) {
System.out.println("i like"+food);
}
}
//问题一:如何根据加载到内存中的被代理类,动态创建一个代理类及其对象
//问题二:当通过代理类的对象调用方法a时,如何动态调用被代理类中的同名方法a
class ProxyFactory{
//调用此方法,返回一个代理类对象
public static Object getProxyFactory(Object obj){//被代理类的对象
MyInvocationHandler handler = new MyInvocationHandler();
handler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj;//赋值时,需要使用被代理类的对象
public void bind(Object obj){
this.obj=obj;
}
//当我们通过代理类的对象调用方法a时,就会自动调用如下的方法:invoke()
//将被代理类要执行的方法a的功能就声明在invoke()方法中
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
//obj:被代理类的对象
Object returnValue = method.invoke(obj, args);
return returnValue;
}
}
public class pra07 {
public static void main(String[] args) {
SuperMan superMan = new SuperMan();
Human proxyFactory =(Human) ProxyFactory.getProxyFactory(superMan);
String belief = proxyFactory.getBelief();
System.out.println(belief);
proxyFactory.eat("四川麻辣烫");
}
}