Java反射—框架设计的灵魂

本文介绍了框架概念,如vue和ionic框架,其可提高开发效率和降低难度。还阐述了Java程序运行过程,重点讲解反射机制,它是框架灵魂,能在运行期间获取对象。介绍三种获取字节码class对象的方式及获取class对象的用途,如获取构造方法、成员变量等。

一、框架概念

     我们先来说一说什么是框架,框架就好比一个半成品的软件,它提供了一些基础的通用化的组件,可以供开发人员在此基础之上对系统进行开发。

      在开发订餐系统PC端和手机端的时候,我们pc端用的是vue框架,手机端用的是ionic框架,vue框架涉及到很多关于事物处理、权限管理、安全性、数据流控制,这些成熟的技术是编写框架的人已经设计好了,而我们开发人员只需要在该框架的基础之上完成我们的业务逻辑设计,这样不仅可以提高开发效率,也可以降低开发难度。

      框架最大的有点就是复用性,例如我们所有的项目手机端目前用的是ionic4框架,积分以及订餐等项目用的都是vue框架,使用框架不仅能够提高我们开发效率而且还可以对技术不断地固化复用。

 

二、类加载(将硬盘中的数据加载到内存当中)

   我们来了解一下java程序的运行过程,例如Person p =new Person(),我们可以进行拆解

   第一步, Source源代码阶段:声明一个变量 Person p, 我们将该变量通过javac编译为字节码文件。

   第二步,Class类对象阶段:将变量的字节码文件通过类加载器加载到内存当中,并进行一系列描述,称为class类对象。

   第三步,Runtime运行时阶段:通过class对象创建Person对象

   图片如下:

 

三、反射概念

   反射机制——框架的灵魂,将类的各个组成部分(变量、构造函数、方法)封装为其他对象。

 

 四、为什么用反射?

    例如我们声明一个变量,通过该变量操作一些对象,反射可以在运行期间获取自身能调用的对象。也就是我们输入 . 后就会自动列出该类对象的所有方法,通过对象找该类对应Class对象,说白了就是找该类的属性和方法。也就是说。即我们可以在程序运行过程中操作这些对象。

   使用反射提高java的灵活性和可配置性,可以解耦。

 

五、三种获取字节码class对象的方式

  ①源代码阶段时期,字节码还未加载到内存。

1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
		* 多用于配置文件,将类名定义在配置文件中。读取文件,加载类

 例如我们在使用JDBC过程当中,第一步导包,第二步注册驱动,此时我们通过调用调用

 Class 类的 forName() 静态方法 public static Class<?> forName(String className)

 通过上图可知我们调用的是MySQL数据库的驱动,如果我们换成其他类型的数据库,则需要对数据库驱动名进行修改,所以注册驱动我们通常写在配置文件当中,即源代码阶段获取class对象多用于配置文件。如下图

 ②class对象阶段

2. 类名.class:通过调用类的隐藏类属性class
               * 多用于参数的传递

例子:
Person.class

③运行时阶段,此时已经创建对象,我们可以使用对象获取祖先类Object的方法,public final native Class<?> getClass()

3. 对象.getClass():getClass()方法在Object类中定义着。
		* 多用于对象的获取字节码的方式


例子:通过对象p调用祖先类的方法
Person p = new Person();
p.getClass();

   

六、为什么要获取class对象?

           获取到class对象,我们就可以获取该对象的构造方法、方法、成员变量等一切信息。

我们首先创建一个Person类

package cn.itcast.domain;

public class Person {
    //声明变量
    private String name;
    private int age;

    //不同权限修饰符的成员变量
    public String a;
    protected String b;
    String c;
    private String d;

    //无参构造函数
    public Person() {
    }
    //有参的构造函数
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }


    public void eat(){
        System.out.println("eat...");
    }

    public void eat(String food){
        System.out.println("eat..."+food);
    }
}

①获取成员变量 

public Field getField(String name) 获取指定名称的 public修饰的成员变量
public Field[] getFields()  获取所有public修饰的成员变量,必须是public修饰的成员变量

public Field getDeclaredField(String name)
public Field[] getDeclaredFields()获取所有的成员变量,不考虑修饰符

 ?获取成员变量做什么 ?

 获取成员变量的值

* get(Object obj) 

  为成员变量设置值

* void set(Object obj, Object value)  

 注意:

②获取构造方法

public Constructor<T> getConstructor(Class<?>... parameterTypes)
public Constructor<?>[] getConstructors()
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
public Constructor<?>[] getDeclaredConstructors()

?获取构造方法做什么 ? ——创建对象——T newInstance(Object... initargs)

//获取Person的Class对象
Class personClass = Person.class;

//获取带参数的构造方法
Constructor constructor = personClass.getConstructor(String.class, int.class);
System.out.println(constructor);
//创建对象
Object person = constructor.newInstance("张三", 23);
System.out.println(person);


//获取无参的构造方法
Object o = personClass.newInstance();
System.out.println(o);

③获取方法

public Method getMethod(String name, Class<?>... parameterTypes)
public Method[] getMethods()
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
public Method[] getDeclaredMethods()

?获取方法做什么 ?——执行方法体——Object invoke(Object obj, Object... args) 

public static void main(String[] args) throws Exception {

        //获取Person的Class对象
        Class personClass = Person.class;
       
        //获取指定名称的方法——不带参数列表的方法
        Method eat_method = personClass.getMethod("eat");
        Person p = new Person();
        //执行方法
        eat_method.invoke(p);

        //获取指定名称的方法——带参数列表的方法
        Method eat_method2 = personClass.getMethod("eat", String.class);
        //执行方法
        eat_method2.invoke(p,"水");

       
        //获取所有public修饰的方法
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
            String name = method.getName();
            System.out.println(name);
            //method.setAccessible(true);
        }


    }

④获取类名

public String getName() // 返回 Class 对象表示的类型(类、接口、数组或基本类型)的完整路径名字符串 
//获取类名
        String className = personClass.getName();
        System.out.println(className);//cn.itcast.domain.Person

 ⑤获取注解

public boolean isAnnotation()
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
public Annotation[] getAnnotations()
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass)
public Annotation[] getDeclaredAnnotations()
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass)
public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass)

⑥其他方法

public T newInstance() // 此方法是 Java 语言 instanceof 操作的动态等价方法
public ClassLoader getClassLoader() // 获取该类的类加载器
public Class<? super T> getSuperclass() // 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class
public boolean isArray() // 如果 Class 对象表示一个数组则返回 true, 否则返回 false
public boolean isInterface() // 判定指定的 Class 对象是否表示一个接口类型
public boolean isPrimitive() // 判定指定的 Class 对象是否表示一个 Java 的基本类型

关于反射,就先分享到这里,自己只能了解到一点皮毛,后续将持续学习反射机制。记得关注点赞哦!

评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值