反射(类的加载)

类的加载

类的加载概述
	当程序要使用某个类时 如果该类还没被加载到内存中 则系统会通过加载 连接 初始化三步来实现对这个类进行初始化加载
	就是指将class文件读入内存 并为之创建一个Class对象
	任何类被使用时系统都会建立一个Class对象
	
	连接
	验证: 是否有正确的内部结构 并和其他类协调一致
	准备: 负责为类的静态成员分配内存 并设置默认初始化值
	解析: 把类中的符号引用转换为直接引用
	初始化
类的加载时机
	创建类的实例 new Student()  
	访问类的静态变量 或者为静态变量赋值 Math.PI Math.class  
	调用类的静态方法 Math.abs()
	使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
	初始化某个类的子类
	直接使用java.exe命令来运行某个主类 

类加载器

类加载器
	负责将.class文件加载到内存中 并为之生成对应的Class对象
类加载器的分类
	Bootstrap ClassLoader 根类加载器
	Extension ClassLoader 扩展类加载器
	System ClassLoader 系统类加载器
类加载器的作用
	1. Bootstrap ClassLoader 根类加载器
		引导类加载器 负责Java核心类的加载
		如String,System等
        在JDK中JRE的lib目录下rt.jar文件中
	2. Extension ClassLoader 扩展类加载器
		负责JRE的扩展目录中jar包的加载
		在JDK中JRE的lib目录下的ext目录
	3. System ClassLoader 系统类加载器
		负责JVM启动时加载来自java命令的class文件 以及classpath环境变量所指定的jar包和类路径

双亲委派机制

工作原理:
1.如果一个类加载器收到了类加载请求 它并不会自己先去加载 而是把这个请求委托给父类的加载器去执行 
2.如果父类加载器还存在其父类加载器 则进一步向上委托 依次递归 请求最终将到达项层的启动类加载器 
3.如果父类加载器可以完成类加载任务 就成功返回 倘若父类加载器无法完成此加载任务 子加载器才会尝试自己去加载 这就是双亲委派机制 

为什么要采用双亲委派机制
1. 避免核心API被篡改
2. 避免类的重复加载	

反射

概述:
	在运行状态中 对于任意一个类,都能够知道这个类的所有属性和方法 对于任意一个对象,都能够调用它的任意一个方法和属性

用处:
	1.类
	判断任意一个对象是否属于某个类(找到对象对应的类)
	运行时构造某个类的一个对象
	2.对象
	判断任意一个对象具有的属性和方法
	运行时调用任意一个对象的方法
	
类的成员:
	成员变量---Field
	构造方法---Constructor
	成员方法---Method

反射获取class文件对象

a: 创建对象 对象调用getClass()方法
b: 类名调用静态属性class
c: Class类中静态方法forName("传入全类名 需要加上包名")
public class MyTest {
    public static void main(String[] args) throws ClassNotFoundException {
        //字节码文件对象只加载一次

        //方式一
        Student student = new Student();
        Class<? extends Student> aClass = student.getClass();
        //方式二
        Class<Student> studentClass = Student.class;
        //方式三  org.反射.获取文件字节码.Student
        Class<?> aClass1 = Class.forName("org.反射.获取文件字节码.Student");
    }
}

反射获取构造方法

public Constructor<?>[] getConstructors()
获取所有的公共的构造方法 不含有私有构造方法
public Constructor<?>[] getDeclaredConstructors()
获取所有的构造方法 包括私有构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
获取单个的公共的构造方法 不包含私有的构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
获取单个的构造方法 包含私有的构造方法
public class MyTest01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        Class<?> studentClass = Class.forName("org.反射.获取构造方法及创建对象.Student");

        //反射获取构造方法

        System.out.println("获取所有的公共的构造方法 public修饰的构造方法");
        Constructor<?>[] constructors1 = studentClass.getConstructors();
        for (Constructor<?> constructor : constructors1) {
            System.out.println(constructor);
        }
            /*public org.反射.获取构造方法.Student()
            public org.反射.获取构造方法.Student(int)*/

        System.out.println("=====================================");
        System.out.println("获取所有的构造方法");
        Constructor<?>[] constructors2 = studentClass.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors2) {
            System.out.println(constructor);
        }
            /*public org.反射.获取构造方法.Student()
            public org.反射.获取构造方法.Student(int)
            private org.反射.获取构造方法.Student(java.lang.String,int)*/

        System.out.println("=====================================");
        System.out.println("获取单个的公共的构造方法 无参构造");
        Constructor<?> constructor = studentClass.getConstructor();
        System.out.println(constructor);
            //public org.反射.获取构造方法.Student()
        
        System.out.println("获取单个的公共的构造方法 1个参数构造");
        Constructor<?> constructor1 = studentClass.getConstructor(int.class);
        System.out.println(constructor1);
            //public org.反射.获取构造方法.Student(int)

        System.out.println("=====================================");
        System.out.println("获取单个的构造方法 私有构造");
        Constructor<?> declaredConstructor = studentClass.getDeclaredConstructor(String.class, int.class);
        System.out.println(declaredConstructor);
            //private org.反射.获取构造方法.Student(java.lang.String,int)
    }
}

反射创建对象

public T newInstance(Object... initargs) 
使用空参数构造方法创建对象
通过反射的构造方法创建对象(initargs-传入对象的属性值)
public void setAccessible(boolean flag)。
通过私有构造方法创建对象是 取消语法检查不报错(flag->true)
public class MyTest02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        
        Class<?> studentClass = Class.forName("org.反射.获取构造方法及创建对象.Student");
        //反射创建对象

        //通过public 无参构造创建对象
        Constructor<?> constructor01 = studentClass.getConstructor();
        Student student = (Student) constructor01.newInstance();
        System.out.println(student);
            //Student{name='null', age=0}

        //通过public 1个参数构造创建对象
        Constructor<?> constructor02 = studentClass.getConstructor(int.class);
        student = (Student) constructor02.newInstance(55);
        System.out.println(student);
            //Student{name='null', age=55}

        //通过private 2个参数构造创建对象
        Constructor<?> constructor03 = studentClass.getDeclaredConstructor(String.class,int.class);
        constructor03.setAccessible(true);
        student = (Student) constructor03.newInstance("张三", 15);
        System.out.println(student);
            //Student{name='张三', age=15}
    }
}

反射获取成员变量

public Field[] getFields() 
获取所有公共的成员变量 包含从父类继承过来的
public Field[] getDeclaredFields() 
获取所有的成员变量 包含私有的 也包含从父类继承过来的成员变量
public Field getField(String name) 
获取单个指定名称name的公共成员变量 不包含私有的
public Field getDeclaredField(String name)
获取单个指定名称的成员变量 包含私有的
public Object get(Object obj) 
获取值 传入创建的对象
public void set(Object obj, Object value) 
设置值 传入创建的对象及其设置的值
public class MyTest {
    public static void main(String[] args) throws NoSuchFieldException {
        Class<Student> studentClass = Student.class;
        
        System.out.println("获取public修饰的所有成员变量");
        Field[] fields = studentClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
            /*public java.lang.String org.反射.获取成员变量.Student.name
            public int org.反射.获取成员变量.Student.age*/

        System.out.println("=======================================");
        System.out.println("获取所有的成员变量");
        Field[] declaredFields = studentClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
            /*public java.lang.String org.反射.获取成员变量.Student.name
            public int org.反射.获取成员变量.Student.age
            private java.lang.String org.反射.获取成员变量.Student.school*/

        System.out.println("=======================================");
        System.out.println("通过指定的成员变量名称 获取public修饰单个成员变量");
        Field field = studentClass.getField("name");
        System.out.println(field);
            //public java.lang.String org.反射.获取成员变量.Student.name
        
        field = studentClass.getField("age");
        System.out.println(field);
            //public int org.反射.获取成员变量.Student.age
        
        System.out.println("=======================================");
        System.out.println("通过指定的成员变量名称 获取任意类型修饰单个成员变量");
        field = studentClass.getDeclaredField("school");
        System.out.println(field);
            //private java.lang.String org.反射.获取成员变量.Student.school
    }
}

public class MyTest02 {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        Class<Student> studentClass = Student.class;
        Constructor<Student> constructor = studentClass.getConstructor();
        Student student = constructor.newInstance();

        //设置值
        Field field = studentClass.getField("name");
        field.set(student,"张三");
        System.out.println(student);
            //Student{name='张三', age=0, school='null'}
        
        //获取值
        String name = (String) field.get(student);
        System.out.println(name);
            //张三
    }
}

反射获取成员方法

public Method[] getMethods() 
获取所有的公共的成员方法 不包含私有的 包含父类继承过来的公共方法
public Method[] getDeclaredMethods() 
获取所有的成员方法 包含私有的
public Method getMethod(String name,Class<?>... parameterTypes) 
获取单个的成员方法 不包含私有的
传入方法名,参数类型
public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 
获取单个的成员方法 包含私有的
public Object invoke(Object obj, Object... args) 
执行方法 传入对象名 参数
public class MyTest {
    public static void main(String[] args) throws NoSuchMethodException {
        Class<Student> studentClass = Student.class;

        System.out.println("获取所有的public的成员方法");
        Method[] methods = studentClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
            /*public void org.反射.获取成员方法.Student.show(java.lang.String,int)
            public static void org.反射.获取成员方法.Student.ok()
            public final void java.lang.Object.wait() throws java.lang.InterruptedException
            public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
            ......... */

        System.out.println("===============================");
        System.out.println("获取所有的的成员方法");
        methods = studentClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
            /*public void org.反射.获取成员方法.Student.show(java.lang.String,int)
            public static void org.反射.获取成员方法.Student.ok()
            private int org.反射.获取成员方法.Student.haha(int)*/

        System.out.println("===============================");
        System.out.println("获取public单个的成员方法");
        Method method = studentClass.getMethod("show", String.class, int.class);
        System.out.println(method);
            //public void org.反射.获取成员方法.Student.show(java.lang.String,int)
        method = studentClass.getMethod("ok");
        System.out.println(method);
            //public static void org.反射.获取成员方法.Student.ok()

        System.out.println("===============================");
        System.out.println("获取单个的成员方法");
        method = studentClass.getDeclaredMethod("haha", int.class);
        System.out.println(method);
            //private int org.反射.获取成员方法.Student.haha(int)
    }
}

public class MyTest02 {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<Student> studentClass = Student.class;
        Constructor<Student> constructor = studentClass.getConstructor();
        Student student = constructor.newInstance();

        Method method = studentClass.getMethod("show", String.class, int.class);
        //public void show(String name, int age) { System.out.println(name + " " + age); }
        Object jack = method.invoke(student, "jack", 18);
        
        method = studentClass.getDeclaredMethod("haha", int.class);
        //private int haha(int age) { return 100; }
        method.setAccessible(true);
        Object invoke = method.invoke(student, 85);
        System.out.println(invoke);
    }
}

运行配置文件内容

/*
config.properties
className=org.Dog
methodName=eat
*/
public class MyTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Properties properties = new Properties();
        properties.load(new FileInputStream("config.properties"));

        //创建对象
        Class<?> aClass = Class.forName(properties.getProperty("className"));
        Object o = aClass.getDeclaredConstructor().newInstance();
        //获取方法 执行方法
        Method declaredMethod = aClass.getDeclaredMethod(properties.getProperty("methodName"));
        declaredMethod.invoke(o);
    }
}

public class Cat {
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

public class Dog {
    public void eat() {
        System.out.println("狗吃骨头");
    }
}

越过泛型检查

public class MyTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(100);
        list.add(200);
        //编译期间通不过泛型检查 。
        //list.add("hello");
        //泛型只在编译期有效,在运行期就擦除了。
        //通过反射机制略过泛型检查

        Class<? extends ArrayList> aClass = list.getClass();
        Method method = aClass.getDeclaredMethod("add", Object.class);
        method.invoke(list,"hello");
        System.out.println(list);
    }
}

动态代理

概述
	可以动态的创建代理并动态的处理对所代理方法的调用
	
	在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口 通过使用这个类和接口就可以生成动态代理对象

特点: 
	字节码随用随创建 随用随加载

作用: 
	不修改源码的基础上对方法增强

分类:
    基于接口的动态代理
    	涉及的类: Proxy
        提供者: JDK官方
    基于子类的动态代理
    
如何创建代理对象:
	1.使用Proxy类中的newProxyInstance方法
    public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
    loader: 类加载器
    interfaces: 接口对应的一个Class数组
    InvocationHandler: 这个其实就是要代理对象所做的事情的一个类的封装
    2.最终会调用InvocationHandler的方法
    InvocationHandler Object invoke(Object proxy,Method method,Object[] args)
    proxy: 代理对象的引用
    method: 当前执行的方法
    args: 当前执行方法所需的参数
    return: 和被代理对象方法有相同的返回值

创建代理对象的要求:
	被代理类最少实现一个接口,如果没有则不能使用  
    
动态代理神奇的地方就是:
    1.代理对象是在程序运行时产生的 而不是编译期 
    2.对代理对象的所有接口方法调用都会转发到InvocationHandler.invoke()方法 在invoke()方法里我们可以加入任何逻辑 比如修改方法参数 加入日志功能 安全检查功能等 之后我们通过某种方式执行真正的方法体    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值