• 《Java基础知识》Java 反射详解


    定义

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

    用途

    在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。案例:(重要)

    1. public class Demo1 {
    2. //创建一个自己本身的公共变量
    3. public static demo.knowledgepoints.reflect.Demo1 demo1;
    4. private static final boolean flag = true ;
    5. //将其私有化,保证不能通过New的方式创建。
    6. private Demo1(){}
    7. //创建get方法,用于告知使用者,不能被new,不能被获取。
    8. public static Demo1 getDemo1() throws Exception{
    9. if(flag){
    10. throw new Exception("抱歉,该类不通过new 的方式创建!");
    11. }
    12. return demo1;
    13. }
    14. public void print(){
    15. System.out.println("恭喜成功获取Demo1!");
    16. }
    17. //通过静态代码块创建实体类。
    18. static {
    19. demo1 = new Demo1();
    20. }
    21. }
    1. public class Demo2 {
    2. //创建一个自己本身的私有变量
    3. private static demo.knowledgepoints.reflect.Demo2 demo2;
    4. private static final boolean flag = true ;
    5. //将其私有化,保证不能通过New的方式创建。
    6. private Demo2(){}
    7. //创建get方法,用于告知使用者,不能被new,不能被获取。
    8. public static Demo2 getDemo2() throws Exception{
    9. if(flag){
    10. throw new Exception("抱歉,该类不通过new 的方式创建!");
    11. }
    12. return demo2;
    13. }
    14. public void print(){
    15. System.out.println("恭喜成功获取Demo2!");
    16. }
    17. //通过静态代码块创建实体类。
    18. static {
    19. demo2 = new Demo2();
    20. }
    21. }

     
    
    1. public class Reflect {
    2. public static void main(String[] args) {
    3. Demo1 demo1 = null;
    4. Demo2 demo2 = null;
    5. try {
    6. //发现new ,编译报错。
    7. //demo1 = new Demo1();
    8. //demo2 = new Demo2();
    9. //发现get方法也获取不到,执行会报异常。
    10. demo1 = Demo1.getDemo1();
    11. demo2 = Demo2.getDemo2();
    12. } catch (Exception e) {
    13. e.printStackTrace();
    14. }
    15. }
    16. }

    运行结果:

    通过上述代码,我们知道通过普通方法是无法获取到Demo1 和 Demo2。但是看Demo1 和 Demo2的写法,在静态代码块中是new了对象的。说明肯定有办法可以获取到实例。这里说的方法就是反射。

    1. import java.lang.reflect.Field;
    2. public class Reflect {
    3. public static void main(String[] args) {
    4. Demo1 demo1 = null;
    5. Demo2 demo2 = null;
    6. try {
    7. //首先通过Field,获取需要的类,Field包在jdk的反射包中:java.lang.reflect
    8. Field field1 = Demo1.class.getDeclaredField("demo1");
    9. //获取之后,强制转换成Demo1。
    10. demo1 = (Demo1)field1.get(null);
    11. demo1.print();
    12. //然后我们再来创建一个Demo2.
    13. Field field2 = Demo2.class.getDeclaredField("demo2");
    14. //私有方法需要将:field2.setAccessible(true) ,才能获取到实例类
    15. field2.setAccessible(true);
    16. demo2 = (Demo2)field2.get(null);
    17. demo2.print();
    18. } catch (Exception e) {
    19. e.printStackTrace();
    20. }
    21. }
    22. }
     
    

    运行结果:

    通过上述代码,我们通过反射,获取到Demo1和Demo2的公共属性和私有属性,成功获取到对象。

    讲讲反射原理:

     通过到class所在目录下,执行javap -c Book.class,可以查看字节码。可以看到一些公共的方法,私有的看不到,不过不影响JVN获取。

    下面介绍一下反射的基础类和方法

    类名用途
    Class类代表类的实体,在运行的Java应用程序中表示类和接口
    Field类代表类的成员变量(成员变量也称为类的属性)
    Method类代表类的方法
    Constructor类代表类的构造方法

    方法见JDK-API文档。


    以下是常见方法的使用案例:

    1. package demo.knowledgepoints.reflect;
    2. public class Book {
    3. private final static String TAG = "BookTag";
    4. private String name;
    5. private String author;
    6. @Override
    7. public String toString() {
    8. return "Book{" +
    9. "name='" + name + '\'' +
    10. ", author='" + author + '\'' +
    11. '}';
    12. }
    13. public Book() {
    14. }
    15. private Book(String name, String author) {
    16. this.name = name;
    17. this.author = author;
    18. }
    19. public String getName() {
    20. return name;
    21. }
    22. public void setName(String name) {
    23. this.name = name;
    24. }
    25. public String getAuthor() {
    26. return author;
    27. }
    28. public void setAuthor(String author) {
    29. this.author = author;
    30. }
    31. private String declaredMethod(int index) {
    32. String string = null;
    33. switch (index) {
    34. case 0:
    35. string = "I am declaredMethod 1 !";
    36. break;
    37. case 1:
    38. string = "I am declaredMethod 2 !";
    39. break;
    40. default:
    41. string = "I am declaredMethod 1 !";
    42. }
    43. return string;
    44. }
    45. }
     
    
    1. package demo.knowledgepoints.reflect;
    2. public class Book {
    3. private final static String TAG = "BookTag";
    4. private String name;
    5. private String author;
    6. @Override
    7. public String toString() {
    8. return "Book{" +
    9. "name='" + name + '\'' +
    10. ", author='" + author + '\'' +
    11. '}';
    12. }
    13. public Book() {
    14. }
    15. private Book(String name, String author) {
    16. this.name = name;
    17. this.author = author;
    18. }
    19. public String getName() {
    20. return name;
    21. }
    22. public void setName(String name) {
    23. this.name = name;
    24. }
    25. public String getAuthor() {
    26. return author;
    27. }
    28. public void setAuthor(String author) {
    29. this.author = author;
    30. }
    31. private String declaredMethod(int index) {
    32. String string = null;
    33. switch (index) {
    34. case 0:
    35. string = "I am declaredMethod 1 !";
    36. break;
    37. case 1:
    38. string = "I am declaredMethod 2 !";
    39. break;
    40. default:
    41. string = "I am declaredMethod 1 !";
    42. }
    43. return string;
    44. }
    45. }

    运行结果:


     尚学堂给同学们带来全新的Java300集课程啦!java零基础小白自学Java必备优质教程_手把手图解学习Java,让学习成为一种享受_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1qL411u7eE?spm_id_from=333.337.search-card.all.click&vd_source=3117718bf474f48fd81d26049c0c97ac

  • 相关阅读:
    爆款小游戏用的都是什么游戏开发引擎?
    bootstrap柵格
    可视化神经网络实验报告,可视化神经网络工具
    (二)、基于 LangChain 实现大模型应用程序开发 | 对话记忆模块 Memory
    【UML】浅谈为什么要有UML?
    Git基础指令(图文详解)
    72道Java线程面试题,一题一答案,不搞花里胡哨
    Java 多线程 习题
    20221127今天的世界发生了什么
    听说,英特尔要对外开放 x86 授权?
  • 原文地址:https://blog.csdn.net/Limingmingaa/article/details/125338319