首页 > 其他 > 详细

反射机制

时间:2020-10-31 23:45:57      阅读:38      评论:0      收藏:0      [点我收藏+]

1.反射机制的作用

  通过java语言的反射机制可以操作字节码文件,可以读和修改字节码文件

2.反射机制相关类所在包

  java.lang.reflect

3.反射机制相关的重要的类

  java.lang.Class:代表字节码文件

  java.lang.reflect.Method:代表字节码中的方法字节码

  java.lang.reflect.Construotor:代表字节码中的构造方法字节码

  java.lang.reflect.Field:代表字节码中的属性字节码

4.获取类的字节码的三种方式

(1)Class c=Class.forName("完整的类名带包名")

  Class.forName()

       * 1.静态方法
       * 2.方法的参数是一个字符串
       * 3.字符串需要的是一个完整的类名
       * 4.完整类名必须带有包名。java.Lang包也不能省略

1             Class c1=Class.forName("java.lang.String");//c1代表String.cass文件,或者说c1代表String类型
2             Class c2=Class.forName("java.util.Date");//c2代表Date类型
3             Class c3=Class.forName("java.lang.Integer");//c3代表Integer类型
4             Class c4=Class.forName("java.lang.System");//c4代表System类型

(2) 对象.getClass()方法

  java中任何一个对象都有一个方法:getClass()

1 String s="abc";
2 Class x=s.getClass(); //x代表String.class字节码文件,x代表String类型

注:c1和x指向的内存地址相同,都是String类的内存地址

System.out.println(c1==x);  //值是true,“==”判断的是对象的内存地址,这里是true,说明c1和x的内存地址是一样的

技术分享图片

 

(3) java语言中任何一种类型,包括基本数据类型,都有.class属性

  Class z=String.class; //z代表String类型

  Class k=Date.class; //k代表Date类型

  Class f=int.class; //f代表int类型

  Class e=double.class; //e代表double类型

5.反射机制的优点

  可以灵活地实例化对象

  先创建一个User类

1 package bean;
3 public class User {
4     
5     public User(){
6         System.out.println("无参数构造方法");
7     }
9 }

  第一种实例化User对象的方式:传统的方式,即通过new方法实例化出一个对象

1 package Reflect;
2 import bean.User;//引入包
3 
4 public class ReflectTest03 {
5     public static void main(String[] args) throws Exception{
6         User user=new User();
7         }
8 }    

  第二种方法:先写一个配置文件classinfo.properties

className=bean.User

  然后读取这个配置文件中的className,再通过反射机制来实例化User对象

 1 package Reflect;
 2 import java.io.FileNotFoundException;
 3 import java.io.FileReader;
 4 import java.util.Properties;
 5 public class ReflectTest03 {
 6     public static void main(String[] args) throws Exception{
 8         FileReader reader=new FileReader("classinfo.properties");//通过IO流读取classinfo.properties文件
 9         Properties pro=new Properties();//创建属性类别对象Map
10         pro.load(reader);//加载
11         reader.close();//关闭
12         String className=pro.getProperty("className");//通过key获取value
13         System.out.println(className);//打印类名
14         
15         //通过反射机制实例化对象
16         Class c=Class.forName(className);
17         Object o=c.newInstance();
18         System.out.println(o);//打印类
20     }
22 }

  这里也许没有直观的体现出灵活性在哪,有时候可能会因为觉得方法二的代码量比较多,反而觉得它不如方法一。但是做这样一种设想,如果此时我们要重新实例化一个对象,如果采用第一种方法的话,我们需要重新编写代码,使用new方法来实例化对象,而如果采用第二种方法,我们直接修改配置文件中className的值,不需要再对其它代码做修改。这便是灵活性的体现:

  例如:再实例化一个Date对象

  方法一:

1 package Reflect;
2 import java.util.Date;
3 import java.util.Properties;
4 public class ReflectTest03 {
5     public static void main(String[] args) throws Exception{
6         Date date=new Date();
7             }
8 }

  方法二:

  直接修改配置文件classinfo.properties中className的值

className=java.util.Date

  其他代码无需改动

6.研究:Class.forName

 1 package Reflect;
 2 
 3 public class ReflectTest04 {
 4     public static void main(String[] args){
 5         try {
 6             Class.forName("Reflect.MyClass");
 7         } catch (ClassNotFoundException e) {
 8             // TODO Auto-generated catch block
 9             e.printStackTrace();
10         }
11     }
12 
13 }
14 
15 class MyClass{
16     //静态代码块在类加载时执行,并且只执行一次
17     static{
18         System.out.println("MyClass类的静态代码块执行了!");
19     }
20 }

运行结果:

技术分享图片

  可以看到静态代码块执行了,这也就说明类被加载了,因为类的加载会导致静态代码块的执行

  所以,如果只希望一个类的静态代码块执行,而不希望其他代码执行,可以使用Class.forName(“完整类名”),这个方法的执行会导致类加载,而类加载时会导致静态代码块执行。

7.研究文件路径的问题

  (1)一般获取路径的方法:

  FileReader reader=new FileReader("classinfo.properties");

  存在缺陷:如果代码离开eclipse,那么当前路径可能就不是project的根了,这时这个路径就无效了。可移植性差

  (2)通过:Thread.currentThread().getContextClassLoader().getResource(" ").getPath();方法获取文件的绝对路径

1 package Reflect;
2 import java.io.FileNotFoundException;
3 import java.io.FileReader;
4 public class AboutPath {
5     public static void main(String[] args) throws Exception{
6     String path=Thread.currentThread().getContextClassLoader().getResource("classinfo2.properties").getPath();
7     System.out.println(path); //通过打印可以发现获取到了文件的绝对路径
8     }
9 }

运行结果:

技术分享图片

  可以看到,获取到了classinfo2.properties文件的绝对路径。

  解释:

  Thread.currentThread() 当前线程对象

   getContextClassLoader() 线程对象的方法,可以获取到当前线程的类加载器对象

  getResource("   ") 这是类加载器对象的方法,当前线程的类加载器默认从类的根路径下加载资源。即文件的起点是src

  注意:

  使用该方法的前提是,这个文件必须在类路径下什么是类路径下:凡是在src下的都是类路径下.(src是类的路径)

  技术分享图片

反射机制

原文:https://www.cnblogs.com/Leeyoung888/p/13907082.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!