Java基础--反射机制的知识点梳理

简介: 什么是反射?   正常编译执行java文件时,会生成一个.class文件,反射就是一个反编译的过程,它可以通过.class文件得到一个java对象.一个类会有很多组成部分,比如成员变量,成员方法,构造方法等,反射可以通过加载类,解剖出类的各个组成部分.

什么是反射?

  正常编译执行java文件时,会生成一个.class文件,反射就是一个反编译的过程,它可以通过.class文件得到一个java对象.一个类会有很多组成部分,比如成员变量,成员方法,构造方法等,反射可以通过加载类,解剖出类的各个组成部分.

为什么要用反射?

  我们需要访问一个类的方法或字段的时候,直接new一个该类的对象然后调用就好了,干嘛要用反射呢,刚学的时候我也不懂,并且学了也没机会用到,或者根本用不到,后来开始接触strut2,hibernate等一些框架的时候,才慢慢懂得了一点反射的强大之处,在框架中会有很多配置文件,而配置文件中一般只有一些类的全路径的字符串,而就是通过这些个字符串,就能得到这个类的对象,以及类中所有的信息.我给你这个类,当然你可以轻松得到它的实例,但如果我给你的只是这个类的路径的字符串呢?没有反射你就傻眼了吧.学习反射一般只会在写框架的时候用到,如果你没有到达写框架的高度,能够看懂别人的框架也是极好的.

这里面还涉及到一个静态编译和动态编译的概念,前者的意思就是在编译的时候已经绑定了对象,确定了对象,而动态编译就是知道运行的时候,才根据需要去绑定对象.

加载类:

  加载类就是获得类的字节码,要想通过反射获取到一个类的内部信息,首先得先获取到这个类的字节码对象.

  加载类有三种方式:

现在我有一个类User,我希望加载这个类,获得它的字节码对象:

package com.wang.reflect;

public class Demo01 {

    public static void main(String[] args) throws ClassNotFoundException {
        
        //第一种方式   通过Class的forName方法,注意使用目标类的全路径
        Class clazz=Class.forName("com.wang.reflect.User");
        
        //第二种方式 通过Object类的getClass()方法
        Class clazz1=new User().getClass();
        
        //第三种方式  通过类的.class属性
        Class clazz2=User.class;
    }
}

  一般第一种方式最常用,也最好用,因为看代码我们可以发现,后两种在编译前就必须要知道具体的类的,否则就无法通过编译,而第一种方式,没有那么大的强制性,他只是提供了一个空间,运行时你可以想把谁传给它就把谁传给它,这个类甚至可以不存在,后果只是抛出一个异常.

 

反射类的构造函数(Constructior):

  获得了Class对象以后就可以调用class的很多方法了,比如getConstructor(..),方法就可以获得构造器的对象.下面分别通过获取User类的无参和带参构造器,进而得到该类对象的例子,感受一下反射技术.

public class User {

    private String name;
    
    public User(){
        System.out.println("无参构造函数");
    }
    
    public User(String name){
        this.name=name;
        System.out.println("带一个参数的构造函数:::"+name);
    }
}
//-----------------------------------------------------------------------------
@Test
    public void test01() throws Exception{
        //通过Class的forName方法,注意使用目标类的全路径
        Class clazz=Class.forName("com.wang.reflect.User");
        
        //通过无参构造器得到该类对象,
        Constructor c=clazz.getConstructor(null);
        User user=(User) c.newInstance(null);
        
        //通过带参构造器获得该类对象
        Constructor c1=clazz.getConstructor(String.class);
        User user1=(User)c1.newInstance("nick");
    }

注意.在通过无参构造函数获得对象时,还可以直接调用User user=(User)clazz.newInstance();得到,内部的原理也是先调用了无参构造器,如上.注意,使用"newInstance"方法只能调用类的无参构造方法,这个操作实际相当于使用了new进行对象实例化.

 

反射类的方法(Method):

  一个类中总会有实现某些功能的方法,这些方法可能有返回值也可能没有返回值,可能有参数也可能没参数,可能是静态方法也可能是普通方法.下面通过例子分别讲解:

package com.wang.reflect;

public class User {

    private String name;
    
    public User(){
        System.out.println("无参构造函数");
    }
    
    public User(String name){
        this.name=name;
        System.out.println("带一个参数的构造函数:::"+name);
    }
    //1无参无返回值的方法login
    public void login(){
        
        System.out.println("用户登陆了");
    }
    //2带参有返回值的方法eat
    public String eat(String name){
        System.out.println("name"+"去吃饭去了");
        return "eat";
    }
    //3带参无返回值的静态方法
    public static void sleep(String name){
        System.out.println(name +"去睡觉了");
    }
}
//-----------------------------------------------------------------
@Test
    public void test02() throws Exception{
        User u=new User();    
        //通过Class的forName方法,注意使用目标类的全路径
        Class clazz=Class.forName("com.wang.reflect.User");
        
    //1获取无参无返回值的方法login
        //获得一个方法名为"login"但是没有参数的Method对象
        Method method=clazz.getMethod("login", null);
        //第一个参数:要想执行这个login方法你总得告诉她是哪个User的login方法吧,第二个参数就是login方法的参数,这里为null
        method.invoke(u, null);
    //2获取有参有返回值的方法eat
        Method method1=clazz.getMethod("eat", String.class);
        String agrs=(String)method1.invoke(u, "超人");
    //3获取带参无返回值的静态方法sleep,
     //静态方法 可以不提供User对象,传一个null即可
Method method2=clazz.getMethod("sleep", String.class); method2.invoke(null, "蝙蝠侠"); }

//执行之后打印结果为:

无参构造函数
用户登陆了
超人去吃饭去了
蝙蝠侠去睡觉了

反射类的字段:

@Test
    public void test03() throws Exception{
        User u=new User();
        u.setName("钢铁侠");
        //通过Class的forName方法,注意使用目标类的全路径
        Class clazz=Class.forName("com.wang.reflect.User");
        //注意需要用getDeclareField方法,getField只能获取到public的字段
        Field f=clazz.getDeclaredField("name");
        f.setAccessible(true);
        String name=(String)f.get(u);
        System.out.println(name);
    }

 

 

 

 下面介绍一个使用反射的简单例子:

package com.wang.reflect;

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ResourceBundle;

interface Person {
    public void location(String location);
}

class Student implements Person{

    @Override
    public void location(String location) {
            System.out.println("学生的工作地点是"+location);
    }
    
}
class Teacher implements Person{

    @Override
    public void location(String location) {
        System.out.println("老师的工作地点是"+location);
    }
    
}

class Factory{
    public static Person getInstance(String str) throws Exception, IllegalAccessException, ClassNotFoundException{
        Person person=(Person)Class.forName(str).newInstance();
        return person;
    }
}

public class TestReflect {

    public static void main(String[] args) throws Exception {
        //Person p=(Person)Class.forName("com.wang.reflect.Student").newInstance();
        //p.location("学校");
        Person p=Factory.getInstance("com.wang.reflect.Teacher");
        p.location("学校");
    
    }
}

这个例子使用了简单的工厂模式,调用person的location方法,通过反射,实际应用中并不会出现这样的代码,这里只是做一个反射的运用的演示.在测试代码中,只要简单的修改ForName方法中的字符串,就可以调用相应的方法.

 

相关文章
|
3月前
|
人工智能 缓存 安全
Java中的反射机制:深入探索与应用
Java反射机制是程序运行时动态获取类信息并操作类成员的特性,具备高度灵活性,但也伴随性能与安全风险。本文详解反射的基本用法、高级应用及最佳实践,助你掌握这一强大工具的正确使用方式。
145 0
|
4月前
|
IDE Java 开发工具
Java 基础篇必背综合知识点最新技术与实操应用全面总结指南
本总结梳理了Java 17+的核心知识点与新技术,涵盖基础概念(模块化系统、GraalVM)、数据类型(文本块、模式匹配)、流程控制(增强switch)、面向对象(Record类、密封类)、常用类库(Stream API、HttpClient)、实战案例(文件处理)、构建工具(Maven、Gradle)、测试框架(JUnit 5)、开发工具(IDE、Git)及云原生开发(Spring Boot 3、Docker)。通过理论结合实操,帮助开发者掌握Java最新特性并应用于项目中。代码示例丰富,建议配合实践加深理解。
121 4
|
3月前
|
Java 数据库连接 数据库
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
本文全面总结了Java核心知识点,涵盖基础语法、面向对象、集合框架、并发编程、网络编程及主流框架如Spring生态、MyBatis等,结合JVM原理与性能优化技巧,并通过一个学生信息管理系统的实战案例,帮助你快速掌握Java开发技能,适合Java学习与面试准备。
146 2
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
|
3月前
|
存储 Java 程序员
Java 基础知识点全面梳理包含核心要点及难点解析 Java 基础知识点
本文档系统梳理了Java基础知识点,涵盖核心特性、语法基础、面向对象编程、数组字符串、集合框架、异常处理及应用实例,帮助初学者全面掌握Java入门知识,提升编程实践能力。附示例代码下载链接。
144 0
|
3月前
|
Java 编译器 数据安全/隐私保护
Java 大学期末考试真题与答案 含知识点总结 重难点归纳及题库汇总 Java 期末备考资料
本文汇总了Java大学期末考试相关资料,包含真题与答案、知识点总结、重难点归纳及题库,涵盖Java基础、面向对象编程、异常处理、IO流等内容,并提供完整代码示例与技术方案,助你高效复习备考。
119 3
|
3月前
|
人工智能 前端开发 安全
Java开发不可不知的秘密:类加载器实现机制
类加载器是Java中负责动态加载类到JVM的组件,理解其工作原理对开发复杂应用至关重要。本文详解类加载过程、双亲委派模型及常见类加载器,并介绍自定义类加载器的实现与应用场景。
203 4
|
3月前
|
存储 缓存 安全
Java基础 - 知识点
Java基础知识点涵盖语言特性、面向对象与基本数据类型、缓存池机制、String类特性、参数传递、类型转换、继承、抽象类与接口区别、重写与重载、Object通用方法及关键字使用等核心内容,是掌握Java编程的重要基石。
|
4月前
|
存储 安全 Java
2025 年最新 40 个 Java 基础核心知识点全面梳理一文掌握 Java 基础关键概念
本文系统梳理了Java编程的40个核心知识点,涵盖基础语法、面向对象、集合框架、异常处理、多线程、IO流、反射机制等关键领域。重点包括:JVM运行原理、基本数据类型、封装/继承/多态三大特性、集合类对比(ArrayList vs LinkedList、HashMap vs TreeMap)、异常分类及处理方式、线程创建与同步机制、IO流体系结构以及反射的应用场景。这些基础知识是Java开发的根基,掌握后能为后续框架学习和项目开发奠定坚实基础。文中还提供了代码资源获取方式,方便读者进一步实践学习。
1018 2
|
4月前
|
并行计算 Java API
Java 入门循环结构基础知识点详解
摘要:本文介绍了Java现代循环技术的进阶应用,包括Stream API、响应式编程和模式匹配,展示了如何用Stream API替代传统循环进行声明式集合处理(如过滤、映射和并行计算),以及响应式编程在异步非阻塞场景下的优势。文章还通过电商订单处理系统的案例演示了这些技术的综合应用,并提供了性能优化建议,如合理使用并行处理和避免循环内对象创建。这些现代特性使Java代码更简洁、高效,更适合高并发和I/O密集型场景。
63 1

热门文章

最新文章