1.反射
1.反射详解
1.定义
反射:动态获取类的字节码文件,并对其成员进行抽象
整体的含义:就是想通过字节码文件直接创建对象.
2.获取字节码文件方式
1.通过Object提供的getClass()方法
2.通过每种数据类型都有的一个class属性
3.Class类提供的一个静态方法forName(字符串) 字符串:包名+类名
2.创建对象
注意:class为字节码文件对象,Object才是实例对象
1.有参
Class<?> class1 = Class.forName("com.qf.test.Person");
//先得到有参的构造方法
//这里要写参数的字节码文件对象形式 所有的类型都有字节码文件对象
//相当于 public Person(String name, int age)
Constructor constructor = cls.getConstructor(String.class,int.class);
//Constructor类是从class类中获得的构造方法类,String.class 和int.class为参数类型
Object object = constructor.newInstance("bingbing",18);
System.out.println(object);
2.无参
Class<?> class1 = Class.forName("com.qf.test.Person");
//这是无参的构造函数
Object object = cls.newInstance();
Person person = (Person)object;
person.setName("bingbing");
System.out.println(person.getName());
3.Class
Class类的类表示正在运行的Java应用程序中的类和接口。每个数组也属于一个反映为类对象的类,该对象由具有相同元素类型和维数的所有数组共享。原始Java类型( boolean , byte, char , short , int , long , float和double ),和关键字void也表示为类对象。
类没有公共构造函数。 类对象由Java虚拟机自动构建。
以下示例使用类对象来打印对象的类名称:
forName(String className) //获得class类 ,静态方法
public ClassLoader getClassLoader() //获得类的加载器
public Constructor<?>[] getDeclaredConstructors() //获得类的所有的类的构造方法
public Constructor<?> getDeclaredConstructor() //获得类的构造方法
Field[] field = class1.getDeclaredFields(); //获得所有的属性
Method[] methods = class1.getMethods(); //获得所有的方法
4.Field
1.定义
字节码文件中的属性,将属性抽象为Field
2.Field的方法
public Object get(Object obj) //返回该所表示的字段的值Field 的的对象
public String getName() //返回由此 Field对象表示的字段的名称。
field.setAccessible(true); //重新赋值前需要设置为true
set(object, 数据(int,char,string等)); //为该字段赋值
5.Method
//调用非静态无参
//*.class 参数 "***"函数名
public static void fun1(Class<?> cla) {
//2.获取实例对象
Object object = cla.newInstance();
//3.通过反射得到方法
Method method = cla.getMethod("show");
//4.调用方法,通过调用invoke方法实现
method.invoke(object);
}
//调用非静态有参
public static void fun2(Class<?> cla) {
//2.先得到有参的构造方法
Constructor<?> constructor = cla.getConstructor(String.class,int.class);
Object object = constructor.newInstance("bingibn",10);
//3.通过反射得到方法
Method method = cla.getMethod("callPhone",String.class);
//4.调用方法,通过调用invoke方法实现
method.invoke(object,"110");
}
//调用静态有参
public static void fun3(Class<?> cla) {
//3.通过反射得到方法
Method method = cla.getMethod("run",int.class);
//4.调用方法,通过调用invoke方法实现
method.invoke(null,11);
}
6.实际使用演示
反射获取man,并赋值,取值,使用函数
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException, InterruptedException {
Class<?> class1 = Class.forName("Man");
Field field = class1.getDeclaredField("name");
Method methods = class1.getDeclaredMethod("getName");
System.out.println(field+" "+methods);
Constructor<?> constructor = class1.getConstructor(int.class, String.class, String.class, String.class);
Object obj = constructor.newInstance(1,"2","3","4");
field.setAccessible(true);
field.set(obj,"zhangsan");
System.out.println(methods.invoke(obj)+" "+field.get(obj));
Man man = (Man)obj;
System.out.println(man.getName());
}
2.动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class Bingbing implements TestInter {
public void findHouse() {
System.out.println("冰冰找房");
}
@Override
public void findMeizi() {
// TODO Auto-generated method stub
System.out.println("玩儿");
}
}
interface TestInter {
public void findHouse();
public void findMeizi();
}
class ChenChen implements TestInter {
public void findHouse() {
System.out.println("晨晨找房");
}
@Override
public void findMeizi() {
// TODO Auto-generated method stub
System.out.println("过七夕");
}
}
public class demo5 {
public static void main(String[] args) {
TestInter testInter = new ChenChen();
((TestInter) Proxy.newProxyInstance(testInter.getClass().getClassLoader(), new Class[] {TestInter.class},
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("扣一个月的房租作为中介费");
Object object = method.invoke(testInter, args);
System.out.println("哈哈大笑");
return object;
}
}
)).findHouse();
}
}
详细解释
-
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class<?>[] { Foo.class }, handler);
**Foo 为接口的类型,也可以定义为Object类型,这里定义为接口可以直接使用方法。**
-
(Foo)的强制类型转换可以不加,例如实例实现了两个接口,一个为Foo,一个为Too,则在new Class<?>[]
{Foo.class , Too.class}加上,这是因为不知到实例类调用哪一个方法,可以不转型。
-
Foo.class.getClassLoader()为获得类的加载器,加载的是代理对象,所以使用的是对应接口的加载器,但是 由于自定义的类的加载器都是同一个加载器,所以些别的也是可以的,但是推荐写对应接口的类加载器。便于观看。
4.new Class<?> {暂时不知道啥意思,但是只有在里面写了的接口才可以使用对应的方法}
5.handler ,这个就是要实现的方法
详细解释
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("扣一个月的房租作为中介费");
Object object = method.invoke(testInter, args);
System.out.println("哈哈大笑");
return object;
}
}
1.这里的invoke是自动调用的method方法,你实现啥它就是啥,例如调用了findhouse方法,他就是findhouse
2.object proxy是一个动态代理类,打印的getclass是一个proxy0,暂时不知道啥用
3.method就是要实现的方法
4.传递的参数,无参的话就没用了
详细解释
Object object = method.invoke(testInter, args);
1.这里的object为返回值,如果没有的话就为null
2.invoke中的testinter是一个实例,此处也可以直接new 一个,args就是上面传递的参数。