目录
有一个ArrayList集合里面存储的都是String,ArrayList如何通过反射给里面存储Integer类型的元素?
反射
反射:(Relection),一个类在加载运行状态的时候,可以动态获取正在运行的类(Class)
创建正在运行类的对象(构造器-Constructor)
使用正在运行的这个类的对象去给成员变量赋值(Field)
调用正在运行的这个类中成员方法(Method)
反射应用----Java设计模式
正射 ---- 就是我们自己书写的代码的时候, 类名 对象名 = new 类名 ();
获取一个类的字节码文件的方式
1)调用Object类的getClass方法
2)任意Java类型的class属性
3)Java提供类Class:表示正在运行的Java应用程序中的累的接口
有一种静态方法:
参数:类的完全限定名称。(包名。类名)
public static Class<?> forName (String className);
public class Person {
private String name ; //私有的姓名
int age ; //默认修饰符的年龄
private String address ; //住址
//公共的无参构造方法
public Person(){}
//默认修饰符的带有两个参数的构造方法
Person(String name,int age){
this.name = name ;
this.age = age ;
}
//私有的:带有三个参数的构造方法
private Person(String name,int age,String address){
this.name = name ;
this.age = age ;
this.address = address ;
}
//一堆成员方法
//是否带参/是否有返回值
public void show(String name){
System.out.println(name) ;
}
private String method(int number){
return "hello"+number ;
}
protected void function(){
System.out.println("function Person...");
}
//默认修饰符
String myFunction(){
return "今天很nice!" ;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//创建当前类对象
Person p = new Person() ;
System.out.println(p.getClass()) ;//class com.qf.reflect_02.Person
Class c2 = Person.class ;
System.out.println(c2) ;
System.out.println(p.getClass() ==c2) ;
System.out.println("-----------------------------") ;
//Class<?> c3 = Class.forName("Person");//参数必须:类的全限定名称
Class<?> c3 = Class.forName("com.qf.reflect_02.Person");
System.out.println(c3);
System.out.println(c3==c2);
}
}
反射的方式:动态获取类的构造器
public class ReflectDemo2 {
public static void main(String[] args) throws Exception{
System.out.println("------反射的方式:动态获取类的构造器并创建实例----");
//1)获取正在运行的类的字节码文件对象
Class c = Class.forName("com.qf.reflect_02.Person");
//2)获取指定的构造器的Constructor对象,创建当前类实例
//public Constructor<T> getConstructor(Class<?>... parameterTypes)
//获取指定的公共的构造方法的Constructor对象,参数:指定参数类型的Class类对象,如果没有参数,可以不写
//举例:String类型的参数---java.lang.String
//int---->java.lang.Integer
Constructor con = c.getConstructor();
//System.out.println(con);//public com.qf.reflect_02.Person()
//Constructor提供一个方法
//参数:通过构造器里面给当前正在运行的类的成员变量赋值:实际参数
//返回T---Type:代表任意Java对象
//public T newInstance(Object... initargs):创建当前类实例
Object obj = con.newInstance() ; // 多态 类似于 --->Object obj = new Person() ;
System.out.println(obj);
System.out.println("----通过有参构造方法当前类实例------------");
//通过当前类的字节码文件对象获取指定的构造方法
//参数是:当前参数类型的字节码文件 String--->String.class
//public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
Constructor con2 = c.getDeclaredConstructor(String.class, int.class, String.class);
//System.out.println(con2);
//构造器所在Constructor继承AccessibleObject 提供
// public void setAccessible(boolean flag) :参数为true:取消Java语言访问检查
con2.setAccessible(true);
//public T newInstance(Object... initargs):创建当前类实例
Object obj2 = con2.newInstance("穆宁雪", 21, "梵雪山");
System.out.println(obj2);
}
//public static void get(int...a){ //a代表多个参数:可变参数(当不明确具体有多个参数的时候,可以使用...)
}
有一个ArrayList集合里面存储的都是String,ArrayList<String>如何通过反射给里面存储Integer类型的元素?
public class ReflectTest {
public static void main(String[] args) throws Exception {
//创建一个ArrayList
ArrayList<String> arrayList = new ArrayList<>() ;
arrayList.add("hello") ;
arrayList.add("world") ;
//通过反射的方式,给里面添加任何元素,调用add(Object obj)
Class c = arrayList.getClass() ;
//通过字节码文件对象获取add方法所在的Method类对象
Method m = c.getDeclaredMethod("add", Object.class) ;
//取消Java语言访问检查
m.setAccessible(true) ;
//直接调用方法,里面传入实际参数
m.invoke(arrayList,100) ;
m.invoke(arrayList,'A') ;
System.out.println(arrayList);
}
}
反射的jdk动态代理
代理设计模式---属于"结构型设计模式"
代理核心思想:代理角色帮助真实角色对他的业务功能进行增强!
静态代理
特点:代理角色和真实角色必须实现同一个接口!
弊端:业务功能和 增强的功能没有完全分离!
动态代理
jdk动态代理--->jdk提供的
java.lang.reflect.Proxy:动态代理类
静态方法:
public static Object newProxyInstance(
ClassLoader loader, //获取接口实例的类加载器
Class<?>[] interfaces,//实现的接口列表的字节码文件(代理类要的实现接口列表的Class)
InvocationHandler h)//有代理实例调用 接口方法的处理程序:接口类型 throws IllegalArgumentException
InvocationHandler:接口
public Object invoke(Object proxy, Method method, Object[] args)
参数1:调用该方法的代理实例
参数2:调用该代理实例的接口方法的Method类对象
参数3:调用接口方法中所有的参数,组成数组,没有参数,可不写
cglib动态代理----不需要接口,基于类就可以实现动态代理
必须提供第三方jar包 (cglib-3.3.0.jar)
针对用户的数据访问接口
public interface UserDao {
/**
* 添加用户操作
*/
void add() ;
/**
* 修改用户
*/
void update() ;
/**
* 删除用户
*/
void delete() ;
/**
* 查询所有用户
*/
void findAll() ;
}
针对用户的数据接口实现
public class UserDaoImpl implements UserDao{
/**
* 添加用户操作
*/
@Override
public void add() {
System.out.println("添加用户操作") ;
}
/**
* 修改用户
*/
@Override
public void update() {
System.out.println("修改用户") ;
}
/**
* 删除用户
*/
@Override
public void delete() {
System.out.println("删除用户") ;
}
/**
* 查询所用
*/
@Override
public void findAll() {
System.out.println("查询所有用户") ;
}
}
优化实现类:多功能进行增强
public class UserDaoImpl2 implements UserDao{
private UserDao ud ;
public UserDaoImpl2(UserDao ud){
this.ud = ud ;
}
@Override
public void add() {
System.out.println("权限校验") ; //---->第三方提供的: 系统监控代码 shiro框架:权限框架/SpringSecurity权限框架
//自己的业务功能
ud.add() ;
System.out.println("产生日志记录");
}
@Override
public void update() {
System.out.println("权限校验" ) ;
//自己的业务功能
ud.update(); ;
System.out.println("产生日志记录");
}
@Override
public void delete() {
System.out.println("权限校验" ) ;
//自己的业务功能
ud.delete(); ;
System.out.println("产生日志记录");
}
@Override
public void findAll() {
System.out.println("权限校验" ) ;
//自己的业务功能
ud.findAll(); ;
System.out.println("产生日志记录");
}
}
代理实例要调用接口方法的处理程序
//自定义一个类实现InvocationHandler接口
//实现invoke方法---->就是调用接口方法
public class MyInvocationHandler implements InvocationHandler {
//声明Object变量
private Object target ;
public MyInvocationHandler(Object target){// 传入真实角色
this.target = target ;
}
/**
* @param proxy 调用该方法的代理实例
* @param method 调用该代理实例的接口方法的Method类对象
* @param args 调用接口方法中所有的参数,组成数组,没有参数,可不写
* @return 从代理实例上的方法调用返回的值
* @throws Throwable 可能调用方法失败!
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("操作业务功能之前,先权限校验!" );
//反射的写法调用接口方法--add()/delete()/udate()/findAll()
Object obj = method.invoke(target, args);
System.out.println("操作业务功能之后,产生日志记录!");
return obj; //方法的返回值
}
}
对用户进行测试
public class UserTest {
public static void main(String[] args) {
//创建UserDao接口对象---子实现类创建
UserDao ud = new UserDaoImpl() ; //ud:真实角色
ud.add() ;
ud.update() ;
ud.delete() ;
ud.findAll();
System.out.println("------------------优化后:对业务功能增强(静态代理)-------------------") ;
UserDaoImpl2 ud2 = new UserDaoImpl2(ud) ; //代理角色
ud2.add() ;
ud2.delete();
ud2.update();
ud2.findAll();
System.out.println("---------------------JDK动态代理实现--------------------------------------------") ;
//接口多态
InvocationHandler handler = new MyInvocationHandler(ud) ;
UserDao ud3 = (UserDao) Proxy.newProxyInstance(
ud.getClass().getClassLoader(),//代理实例要实现的接口的字节码文件---类加载
//代理实例要实现接口列表的Class--->Class类中--public 类<?>[] getInterfaces()
ud.getClass().getInterfaces(),
//代理实例调用接口方法的处理程序
handler);
ud3.add() ;
ud3.delete() ;
ud3.update() ;
ud3.findAll() ;
}
}