java基础复习(4)[编程语言教程]

写在前面

在近半年的学习中,我接触了Spring的很多框架。但Spring框架的核心功能的实现——反射和注解,我却了解很少。今天就来学习一下java中的反射和注解

反射

反射的定义

我们查阅百度,可以看到这样的定义:

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

要理解这段话,我们先来看看java程序的三个阶段:
技术分享图片

java程序有三个阶段,源代码阶段,类对象阶段,运行阶段。而反射的意思,即我们在这三个阶段都可以自由地通过反射来动态获取类的所有信息,并且不对类做任何改变。我们在使用JDBC的第一步,就写了如下的代码:

Class.forName("com.mysql.jdbc.Driver");

这就是获取了jdbc驱动的那个类,这就是反射的用处。我们通过反射,不用了解一个类的内部细节,就可以很方便的对类进行获取。那么我们如何获取一个类对象呢?

获取

获取一个类的方式有三种,分别对应java运行的三个时期:

  • 源代码阶段:

    Class.forName("全类名")
    
  • Class类对象阶段:

    类名.class
    
  • 运行阶段:

    对象.getClass()
    

我们来写一段示例代码来分别测试这三种方式:

        // 1.Class.forName("全类名")
        Class cls1 = Class.forName("com.liuge.demo06.domain.Person");
        System.out.println(cls1);
        // 2.类名.class
        Class<Person> cls2 = Person.class;
        System.out.println(cls2);
        // 3.对象.getClass()
        Person p = new Person();
        Class cls3 = p.getClass();
        System.out.println(cls3);
        // == 比较三个对象
        System.out.println(cls1 == cls2);
        System.out.println(cls1 == cls3);

我们输出,会发现最后的相等语句输出的是true,说明同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

使用

我们获取了类对象后,有什么作用呢?总的来说我们有三种用处:1.获取成员变量,2.获取构造方法,3.获取成员方法,4.获取全类名。我们一一来说:

  • 获取成员变量

    先看代码:

      public static void main(String[] args) throws Exception {
            // 1.获取Person的Class对象
            Class personClass = Person.class;
            // 1.1获取成员变量(public)
            Field[] fields = personClass.getFields();
            for (Field field : fields) {
                System.out.println("field = " + field);
            }
            System.out.println("===========");
            Field a = personClass.getField("a");
            // 获取成员变量a的值
            Person p = new Person();
            Object value = a.get(p);
            System.out.println("value = " + value);
            // 设置a的值
            a.set(p,"王五");
            System.out.println(p);
            System.out.println("===========");
            // 1.2 getDeclaredFields():所有的成员变量
            Field[] declaredFields = personClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                System.out.println("declaredField = " + declaredField);
            }
            Field d = personClass.getDeclaredField("d");
            // 忽略访问权限修饰符的安全检查(暴力反射)
            d.setAccessible(true);
            Object value2 = d.get(p);
            System.out.println("value2 = " + value2);
        }
    

    可以看到,获取成员变量的方法有四种,而这对前三个都是一样的,且作用一样。这里我们获取了成员变量后,常用的事其实就两件:设置值和获取值。具体的都在代码里体现了,可以看看。

  • 获取构造方法

    类似的,构造方法也可以这样获取:

        public static void main(String[] args) throws Exception {
            // 1.获取Person的Class对象
            Class personClass = Person.class;
            // 1.1 获取有参构造方法
            Constructor constructor = personClass.getConstructor(String.class, int.class);
            System.out.println(constructor);
            // 创建对象
            Object person = constructor.newInstance("卧槽", 25);
            System.out.println("person = " + person);
            System.out.println("=========");
            // 1.1 获取空参构造方法
            Constructor constructor1 = personClass.getConstructor();
            System.out.println(constructor);
            // 创建对象
            Object person1 = constructor1.newInstance();
            System.out.println("person1 = " + person1);
    
            Object o = personClass.newInstance();
            System.out.println("o = " + o);
        }
    

    其他的都很类似了,就不再写例子了。

  • 获取成员方法

    这也和上面类似,如下:

            // 1.获取Person的Class对象
            Class personClass = Person.class;
            // 1.1 获取指定名称方法
            Method eat_method = personClass.getMethod("eat");
            // 1.2 执行方法
            Person p = new Person();
            eat_method.invoke(p);
            // 1.3带参方法
            Method eat_method2 = personClass.getMethod("eat", String.class);
            // 1.4执行方法
            eat_method2.invoke(p,"饭");
            System.out.println("==========");
            // 1.5获取所有方法
            Method[] methods = personClass.getMethods();
            for (Method method : methods) {
                String name = method.getName();
                System.out.println("name = " + name);
            }
    
  • 获取类名

    这就很简单了,直接看使用方法:

           // 获取类名
            String className = personClass.getName();
            System.out.println("className = " + className);
    

注解

对于注解,我们在Spring框架中使用的十分频繁。这里我们就简单了解下注解的定义和本质就可

定义

其实定义很简单,就是一种说明给程序看的标识。通过注解我们可以很方便的让这段代码具有某种功能。

本质

我们随便点开一个注解,可以看到:
技术分享图片

我们仔细观察,发现注解有两部分,一部分是头上的注解,称作元注解,一部分是下面的注解定义,这个@interface我们通过反编译就可以看出,其实就是interface,所以我们可以在里面定义抽象方法,这在注解中被称为属性。

总结

总的来说,了解了反射和注解的本质后,对于Spring框架的源码也算是稍微更加理解了一点吧。java的基础复习到这里就结束了。总的来说学到了很多。

java基础复习(4)

原文:https://www.cnblogs.com/wushenjiang/p/13358184.html

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » java基础复习(4)