当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过 加载,连接,初始化三步 来实现对这个类的初始化。
类加载器负责将.class文件加载到内在中,并为之 生成对应的Class对象。
工作原理:
为什么要采用双亲委派机制?
说通俗点, 如果可以随意的就去执行自己写的String了,那么有人进行恶意攻击, 给你发送一个String类,项目就会直接崩溃! 所以这也是一种保护。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取类的信息以及动态调用对象的方法的功能称为java语言的反射机制。要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。反射就是在运行状态中的一种动态调用方法或者属性的一种机制.就是 获取字节码文件对象,然后剖析该类中存在哪些构造方法(Constructor),哪些成员变量(Field),哪些成员方法(Method)
- public class MyTest {
- public static void main(String[] args) throws ClassNotFoundException {
- //方式1:getClass方法
- Student student = new Student();
- Student student2 = new Student();
- Class extends Student> aClass = student.getClass();
- Class extends Student> aClass1 = student2.getClass();
-
-
- //方式2:每个类,都有一个 class属性,通过他就可以获取
- Class
studentClass = Student.class; -
- //方式3:Class类中的一个静态方法forName
- Class> aClass2 = Class.forName("org.xingyun.demo2.Student");
- }
- }
-
- package org.xingyun.demo2;
-
- public class Student {
- }
之前我们创建一个类的对象,通过new调用构造方法来创建,因为只要能调用到这个类的构造方法,就能创建该类的对象。现在采用反射的方式来创建一个类的对象, 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。 通过这个类的字节码文件对象,就能够获取到这个类的构造方法对象。 获取构造方法对象的方法如下:
- public class MyTest {
- public static void main(String[] args) throws ClassNotFoundException {
-
- //获取字节码文件对象(方式3)
- Class> aClass = Class.forName("org.xingyun.demo3.Student");
-
- //获取所有的公共的构造方法对象
- Constructor>[] constructors = aClass.getConstructors();
- //循环输出
- for (Constructor> constructor : constructors) {
- System.out.println(constructor);
- }
-
- //获取所有的构造方法对象包括私有的构造方法对象
- Constructor>[] declaredConstructors = aClass.getDeclaredConstructors();
- for (Constructor> declaredConstructor : declaredConstructors) {
- System.out.println(declaredConstructor);
- }
-
- //获取空参的构造方法对象
- Constructor> constructor = aClass.getConstructor();
- System.out.println(constructor);
- Constructor> constructor2 = aClass.getConstructor(String.class);
- System.out.println(constructor2);
- Constructor> constructor3 = aClass.getConstructor(String.class, int.class);
- System.out.println(constructor3);
-
- //获取私有的构造方法对象
- Constructor> constructor4 = aClass.getDeclaredConstructor(String.class, int.class, double.class);
- System.out.println(constructor4);
- }
- }
-
- public class MyTest {
- public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
- //获取字节码文件对象,org.xingyun.demo5为路径名
- Class> aClass = Class.forName("org.xingyun.demo5.Teacher");
- //获取所有的成员变量对象,包含私有的
- Field[] declaredFields = aClass.getDeclaredFields();
- for (Field declaredField : declaredFields) {
- System.out.println(declaredField);
- }
-
- //获取所有公共的成员变量对象
- Field[] fields = aClass.getFields();
- for (Field field : fields) {
- System.out.println(field);
- }
-
- //获取单个公共的成员变量对象
- Field nameField = aClass.getField("name");
- System.out.println(nameField);
-
- //获取单个成员变量对象(包含私有成员变量)
- Field sal = aClass.getDeclaredField("sal");
- System.out.println(sal);
-
-
- //给姓名字段设置值
- nameField.set(teacher, "张三");
- //获取字段对象的值
- String nameValue = (String) nameField.get(teacher);
- System.out.println(nameValue);
-
- //给年龄字段设置值
- Field ageField = aClass.getField("age");
- ageField.setInt(teacher, 20);
- //取出年龄字段值
- int anInt = ageField.getInt(teacher);
- System.out.println(anInt);
-
- Field salField = aClass.getDeclaredField("sal");
- salField.setAccessible(true); //取消私有权限的检查
- salField.setDouble(teacher, 3.25);
- double aDouble = salField.getDouble(teacher);
- System.out.println(aDouble);
- }
- }
-
-
- public class Teacher {
- public String name;
- public int age;
- private double sal;
- }
- public class MyTest {
- public static void main(String[] args) throws NoSuchMethodException {
- //获取字节码文件对象
- Class
dogClass = Dog.class; - //获取所有的公共的成员方法对象,包括父类的。
- Method[] methods = dogClass.getMethods();
- for (Method method : methods) {
- System.out.println(method);
- }
-
-
- //获取所有的成员方法对象包括私有的
- Method[] methods2 = dogClass.getDeclaredMethods();
- for (Method method : methods2) {
- System.out.println(method);
- }
- //获取单个公共的成员方法对象
- Method show = dogClass.getMethod("show"); //传入需要获取的方法的方法名
-
- //获取单个公共的带参的成员方法(在后面获取数据类型的类的字节码文件对象)
- Method haha = dogClass.getMethod("haha", String.class, int.class);
-
- //获取单个带参的成员方法(在后面获取数据类型的类的字节码文件对象),可包含私有成员方法
- Method test = dogClass.getDeclaredMethod("test", String.class);
-
- //通过空参构造创建对象,用下面这个也可以
- Dog dog1 = dogClass.newInstance();
- Method show = dogClass.getMethod("show");//传入方法名
- //调用方法执行
- show.invoke(dog1);
-
-
- Method haha = dogClass.getMethod("haha", String.class, int.class);
- Double o = (Double) haha.invoke(dog1, "小黑", 2);
- System.out.println(o);
-
-
- Method test = dogClass.getDeclaredMethod("test", String.class);
- test.setAccessible(true); //取消私有权限检查
- test.invoke(dog1, "abc");
- }
- }
-
-
-
-
- public class Dog {
-
- public void show() {
- System.out.println("我是小白");
- }
-
- public double haha(String name, int age) {
- System.out.println("哈哈" + name + "===" + age);
-
- return 3.25;
- }
-
- private void test(String name) {
- System.out.println("私有的方法调用了" + name);
- }
-
- }
代理形象点就是, 本来应该自己做的事情,却请了别人来做,被请的人那就是代理对象。而 动态代理便是在程序运行过程中产生的这个对象 。在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的静态方法获取一个代理对象 , 最终调用InvocationHandler的方法来实现。
特点 | 字节码随用随创建,随用随加载 |
作用 | 不修改源码的基础上对方法增强 |
涉及的类 | Proxy |
提供者 | JDK官方 |
分类 |
|
强大的代理cglib,使用Proxy类中的 newProxyInstance方法来创建代理对象 。需要注意的是 被代理类最少实现一个接口, 如果没有则不能使用。
public static Object newProxyInstance(ClassLoader loader,Class>[]interfaces,InvocationHandler h) 创建代理对象
newProxyInstance方法中的参数:
InvocationHandler Object invoke(Object proxy,Method method,Object[] args) 同时绑定的一个方法, 执行被代理对象的任何接口方法都会经过该方法
new InvocationHandler() {
/**
* 作用:执行被代理对象的任何接口方法都会经过该方法
* 方法参数的含义
* @param proxy 代理对象的引用
* @param method 当前执行的方法
* @param args 当前执行方法所需的参数
* @return 和被代理对象方法有相同的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
}
}
InvocationHandler 方法调用的实际处理者,代理对象的方法调用都会转发到这里。Proxy.newProxyInstance()会返回一个实现了指定接口的代理对象,对该对象的所有方法调用都会转发给InvocationHandler.invoke()方法。
(小编也在努力学习更多哟!以后再慢慢分享的啦!)
希望对友友们有所帮助!!!!