java反射

主要从这几个方面来介绍:

  • 什么是反射?
  • 理解Class类。
  • 类加载机制
  • 通过反射的操作类方法和属性
  • 动态代理

1.反射机制

反射机制是指Java在运行时,可以获取任意一个类的属性和方法,任意一个对象可以调用它的任意一个方法和属性。这种动态获取信息和调用对象方法的功能称作是Java反射机制。

2.理解Class类

  • Class类是什么?
    • Class类就是用来描述类的类。也就是说它是一个类。
    • //Class的定义
      public final
          class Class<T> implements java.io.Serializable,
                                    java.lang.reflect.GenericDeclaration,
                                    java.lang.reflect.Type,
                                    java.lang.reflect.AnnotatedElement {
      
      .....
      .....
      .....
      }

       

  • 这个类封装了什么信息?

    Class是一个类,它封装了当前对象所对应了的信息。

    一个类中有属性,方法,构造器等,比如说有一个Person类,一个Order类,一个Book类,这些都是不同的类,现在需要一个类,用来描述类,这就是Class,它应该有类名,属性,方法,构造器等。Class是用来描述类的类。

   Class类是一个对象照镜子的结果,对象可以看到自己有哪些属性,方法,构造器,实现了哪些接口等等

  • 如何获取Class对象?
    • 三种方式:
      • 类.class
      • 对象.getClass()
      • Class.forName("xxx")
package basic;

//Person类
public class Person {
    private String name="tom";

    private int age;

    public String sex="男";

    public Person(){}

    public Person(int age){
        this.age=age;
    }

    public void speak(){
        System.out.println("你好!");
    }

    private void eat(){
        System.out.println("好吃");
    }

}
//1.通过类.class获取类对象
Class clazz=Person.class;

//2.对象.class
Person p=new Person();
Class clazz=p.getClass;

//3.Class.forName("")
Class clazz=Class.forName("basic.Person");

3.反射的类加载机制

ClassLoader(类加载器)是用来把class加载到jvm中的,jvm中规范了两种类加载器,启动类加载器(bootstrap)和用户自定义加载器(user-defined classloader).jvm在运行时会产生三个类加载器组成的初始化加载器曾其结构。如下图所示:

public class ReflectionTest {
    public  void Test() throws ClassNotFoundException {
        //1.获取一个类的系统加载器(可以获取,这个类就是它加载的)
        ClassLoader classLoader=ClassLoader.getSystemClassLoader();
        System.out.println(classLoader);

        //2.获取一个系统类加载器的父类加载器(扩展类加载器,可以获取)
        classLoader=classLoader.getParent();
        System.out.println(classLoader);

        //3.获取一个系统类加载器的父类加载器(引导类加载器,不可以获取)
        classLoader=classLoader.getParent();
        System.out.println(classLoader);

        //测试当前类由哪个类加载器加载(系统类加载器)
        classLoader=Class.forName("basic.ReflectionTest").getClassLoader();
        System.out.println(classLoader);

        //测试超类由哪个加载器加载(引导类,不可获取)
        classLoader=Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);

        //使用类加载器获取当前类目录下的文件

        InputStream in1=null;
        InputStream in2=null;
        //src下面可以直接加载
        in1=this.getClass().getClassLoader().getResourceAsStream("text1.txt");

        //不是src下的需要获取全路径
        in2=this.getClass().getResourceAsStream(("basic/test2.txt"));



    }
}

4.通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等

       getName():获得类的完整名字。
  getFields():获得类的public类型的属性。
  getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
  getMethods():获得类的public类型的方法。
  getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
  getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数         指定方法的参数类型。
  getConstructors():获得类的public类型的构造方法。
  getConstructor(Class[] parameterTypes):获得类的特定构造方法,         parameterTypes 参数指定构造方法的参数类型。
  newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

   Class clazz=Class.forName("basic.Person");
        //使用newInstance()创建一个类的对象,调用无参构造器
        Person ob=(Person) clazz.newInstance();
        ob.speak();
        System.out.println(ob);

        //获得类的完整名字
        String classname=clazz.getName();

        //获得类的public属性
        Field [] fields=clazz.getFields();
        for(Field field:fields)
        {
            System.out.println(field.getName());
        }
        //获得类的所有属性
        Field [] fields1=clazz.getDeclaredFields();
        for(Field field1:fields1)
        {
            System.out.println(field1.getName());
        }

        //获得类的public类型的方法。这里包括 Object 类的一些方法
        Method [] methods = clazz.getMethods();
        for(Method method : methods){
            System.out.println(method.getName());//speak  equls toString hashCode notify等
        }

         //获得类的所有方法。
        Method [] allMethods = clazz.getDeclaredMethods();
        for(Method method : allMethods){
            System.out.println(method.getName());//speak eat 不包括object类的方法
        }

        //获得指定的属性
        Field f1 = clazz.getField("sex");
        System.out.println(f1);

        //获得指定的私有属性
        Field f2 = clazz.getDeclaredField("name");
        //启用和禁用访问安全检查的开关,值为 true,则表示反射的对象在使用时应该取消 java 语言的访问检查;反之不取消
        f2.setAccessible(true);
        System.out.println(f2.get(ob));//tom
        //给对象的属性赋值。通过反射机制破坏封装性
        f2.set(ob,"Bob");
        System.out.println(f2.get(ob));//Bob

        //获取构造方法
        Constructor[] constructors = clazz.getConstructors();
        for(Constructor constructor : constructors){
            System.out.println(constructor.toString());//public com.ys.reflex.Person() public basic.Person(int)
        }

5.理解并掌握动态代理

  • 动态代理(以下称代理),利用Java的反射技术(Java Reflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象)
  • 解决特定问题:一个接口的实现在编译时无法知道,需要在运行时才能实现
  • 实现某些设计模式:适配器(Adapter)或修饰器(Decorator)
  • 面向切面编程:如AOP in Spring

参考资料:https://www.cnblogs.com/luoxn28/p/5686794.html

                 https://www.cnblogs.com/tech-bird/p/3525336.html

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值