zoukankan      html  css  js  c++  java
  • 关于JAVA反射机制的学习

    关于JAVA反射机制的学习

    1、基本概念:反射机制(比较简单,因为只要会查帮助文档,就可以了。)

    2.1、反射机制有什么用?
    通过java语言中的反射机制可以操作字节码文件。
    优点类似于黑客。(可以读和修改字节码文件。)
    通过反射机制可以操作代码片段。(class文件。)

    2.2、反射机制的相关类在哪个包下?
      java.lang.reflect.*;

    2.3、反射机制相关的重要的类有哪些?

    java.lang.Class:代表整个字节码,代表一个类型,代表整个类。

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

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

    java.lang.reflect.Field:代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)。

    java.lang.Class:
        public class User{
      // Field
           int no;

     // Constructor
           public User(){

             }
          public User(int no){
              this.no = no;
     }

     // Method
          public void setNo(int no){
                  this.no = no;
        }
          public int getNo(){
            return no;
      }
    }

    3、关于JDK中自带的类加载器:(聊一聊,不需要掌握,知道当然最好!)
    3.1、什么是类加载器?
    专门负责加载类的命令/工具。
    ClassLoader

    3.2、JDK中自带了3个类加载器
    启动类加载器:rt.jar
    扩展类加载器:ext/*.jar
    应用类加载器:classpath

    3.3、假设有这样一段代码:


    String s = "abc";

    代码在开始执行之前,会将所需要类全部加载到JVM当中。
    通过类加载器加载,看到以上代码类加载器会找String.class
    文件,找到就加载,那么是怎么进行加载的呢?

    首先通过“启动类加载器”加载。
    注意:启动类加载器专门加载:C:Program FilesJavajdk1.8.0_101jrelib t.jar
    rt.jar中都是JDK最核心的类库。

    如果通过“启动类加载器”加载不到的时候,
    会通过"扩展类加载器"加载。
    注意:扩展类加载器专门加载:C:Program FilesJavajdk1.8.0_101jrelibext*.jar


    如果“扩展类加载器”没有加载到,那么
    会通过“应用类加载器”加载。
    注意:应用类加载器专门加载:classpath中的类。


    3.4、java中为了保证类加载的安全,使用了双亲委派机制

    优先从启动类加载器中加载,这个称为“父”
    “父”无法加载到,再从扩展类加载器中加载,
    这个称为“母”。双亲委派。如果都加载不到,
    才会考虑从应用类加载器中加载。直到加载
    到为止。

    1、回顾反射机制

    1.1、什么是反射机制?反射机制有什么用?
    反射机制:可以操作字节码文件
    作用:可以让程序更加灵活。

    1.2、反射机制相关的类在哪个包下?
    java.lang.reflect.*;

    1.3、反射机制相关的主要的类?
    java.lang.Class
    java.lang.reflect.Method;
    java.lang.reflect.Constructor;
    java.lang.reflect.Field;

    1.4、在java中获取Class的三种方式?
    第一种:
    Class c = Class.forName("完整类名");
    第二种:
    Class c = 对象.getClass();
    第三种:
    Class c = int.class;
    Class c = String.class;

     1 /**
     2  * 反射
     3  * 要操作一个类的字节码,首先要获取这个类的字节码,怎么获取java.lang.Class实例
     4  * 三种方式
     5  * @author yumu
     6  *
     7  */
     8 public class ReflectTest01 {
     9 
    10     public static void main(String[] args) throws ClassNotFoundException {
    11         /*
    12          * 1.第一种 Class.forName()
    13          * Class.forName(0
    14          *   1.静态方法
    15          *   2.方法的参数是一个字符串
    16          *   3.字符串需要一个完整类名
    17          *   4.完整类名必须带有包名
    18          */
    19             Class c1=Class.forName("java.lang.String");
    20             Class c2=Class.forName("java.util.Date");
    21             Class c3=Class.forName("java.lang.Integer");
    22             Class c4=Class.forName("java.lang.System");
    23             
    24         //第二种 java中任何一个对象都有一个方法:getClass()
    25             String s="abc";
    26             Class x=s.getClass();//x代表String.class字节码文件,x代表String类型
    27             System.out.println(c1==x);  //true
    28             
    29             Date time=new Date();
    30             Class d=time.getClass();
    31             System.out.println(c2==d);  //true
    32             
    33         //第三种 java语言任何一种类型,包括基本数据类型,它都有.class属性
    34             Class z=String.class;  //z代表String类型
    35             Class k=Date.class;    //k代表Date类型
    36             Class f=int.class;     //f代表int类型
    37             Class e=double.class;   //e代表double类型
    38             
    39             System.out.println(x==z);  //true
    40             System.out.println(k==d);        
    41     }
    42 
    43 }

    1.5、获取了Class之后,可以调用无参数构造方法来实例化对象

    //c代表的就是日期Date类型
    Class c = Class.forName("java.util.Date");

    //实例化一个Date日期类型的对象
    Object obj = c.newInstance();

    一定要注意:
    newInstance()底层调用的是该类型的无参数构造方法。
    如果没有这个无参数构造方法会出现"实例化"异常。

      验证反射机制的灵活性

     1 /**
     2  * 验证反射机制的灵活性
     3  *   java代码写一遍,再不改变java源代码的基础上,可以做到不同对象的实例化
     4  * @author yumu
     5  *
     6  */
     7 public class ReflectTest03 {
     8 
     9     public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
    10         //通过IO流读取classinfo.properties文件
    11         FileReader reader=new FileReader("classinfo.properties");
    12         //创建属性类对象Map
    13         Properties pro=new  Properties();
    14         //加载
    15         pro.load(reader);
    16         //关闭流
    17         reader.close();
    18          
    19         //通过key获取value
    20         //配置文件的改变会实例不同的对象
    21         String className = pro.getProperty("className");
    22         //通过反射机制实例化对象
    23         Class c=Class.forName(className);
    24         Object obj=c.newInstance();
    25         System.out.println(obj);
    26         
    27     }
    28 
    29 }

    1.6、如果你只想让一个类的“静态代码块”执行的话,你可以怎么做?
         Class.forName("该类的类名");
        这样类就加载,类加载的时候,静态代码块执行!!!!
        在这里,对该方法的返回值不感兴趣,主要是为了使用“类加载”这个动作。


    1.7、关于路径问题?

    String path = Thread.currentThread().getContextClassLoader()
    .getResource("写相对路径,但是这个相对路径从src出发开始找").getPath();

    String path = Thread.currentThread().getContextClassLoader()
    .getResource("com/bjpowernode/test.properties").getPath();
    //必须保证src下有com目录,com目录下有bjpowernode目录。
    //bjpowernode目录下有test.properties文件。

    这种方式是为了获取一个文件的绝对路径。(通用方式,不会受到环境移植的影响。)
    但是该文件要求放在类路径下,换句话说:也就是放到src下面。
    src下是类的根路径。

    直接以流的形式返回:
    InputStream in = Thread.currentThread().getContextClassLoader()
    .getResourceAsStream("com/bjpowernode/test.properties");

     1 public class ReflectTest05 {
     2 
     3     public static void main(String[] args) throws IOException {
     4         //上面学的路径移植性太差 ,
     5         //接下来说一种通用的方式
     6         //注意:以下方法的前提,这个文件必须在类路径下
     7         //src是类的根路径
     8         /*
     9          * 解释:
    10          * Thread.currentThread() 当前线程对象
    11          * getContextClassLoader() 是线程对象方法,可以获取当前线程的类加载器对象
    12          * getResource [获取资源] 这是类加载器对象的方法,当前线程的类加载器默认从当前类的根路径下加载资源
    13          */
    14         //这是一个获取文件的绝对路径
    15         //String path = Thread.currentThread().getContextClassLoader().getResource("classinfo.properties").getPath();
    16         //FileReader reader =new FileReader(path);
    17         //System.out.println(path);
    18         //这是一种直接以流的形式获取
    19         InputStream reader =Thread.currentThread().getContextClassLoader().getResourceAsStream("classinfo.properties");
    20         
    21         Properties pro = new Properties();
    22         pro.load(reader);
    23         reader.close();
    24         String className = pro.getProperty("className");
    25         System.out.println(className);
    26     
    27     
    28     }
    29 
    30 }

    1.8、IO + Properties,怎么快速绑定属性资源文件?

    //要求:第一这个文件必须在类路径下
    //第二这个文件必须是以.properties结尾。
    ResourceBundle bundle = ResourceBundle.getBundle("com/bjpowernode/test");
    String value = bundle.getString(key);

     1 /**
     2  * java.util包下提供了一个资源绑定器,便于获取属性文件中的内容
     3  * 使用以下方法,属性配置文件xxx.properties必须放到类路径下
     4  * 并且,写路径的时候,路径下面的扩展名不写
     5  * @author yumu
     6  *
     7  */
     8 public class ResourceBundleTest01 {
     9 
    10     public static void main(String[] args) {
    11         ResourceBundle bundle=ResourceBundle.getBundle("classinfo");
    12         String str = bundle.getString("className");
    13         System.out.println(str);
    14     }
    15 
    16 }

    2、今日反射机制的重点内容
    2.1、通过反射机制访问对象的某个属性。

     1 /**
     2  * 必须掌握:
     3  *    怎么通过反射机制访问一个java对象的属性?
     4  *     给属性赋值,
     5  *     获取属性的值get
     6  * @author yumu
     7  *
     8  */
     9 public class ReflectTest08 {
    10 
    11     public static void main(String[] args) throws Exception {
    12         //不使用反射机制,怎么去访问一个对象的属性
    13         Student s=new Student();
    14         s.no=100;
    15         System.out.println(s.no);
    16         
    17         //使用反射机制
    18         Class studentClass=Class.forName("javase.bean.Student");
    19         Object obj = studentClass.newInstance();
    20         //获取属性  靠名字气氛
    21         Field field = studentClass.getDeclaredField("no");
    22         /*
    23          * 虽然是反射机制,但三要素还是一样  
    24          *  要素1:obj对象
    25          *  要素2:no属性
    26          *  要素3:222值
    27          * 注意:反射机制让代码复杂了,但更灵活,这也是值了
    28          * 
    29          */
    30         //设置属性值
    31         field.set(obj, 22222);
    32         //获取属性值
    33         System.out.println(field.get(obj));
    34         
    35         //可以访问私有的属性吗
    36         Field nameField = studentClass.getDeclaredField("name");
    37         //打破封装(反射机制的缺点)
    38         //这样留下安全隐患.外部可以访问private
    39         nameField.setAccessible(true);
    40         nameField.set(obj, "zhangsan");
    41         System.out.println(nameField.get(obj));
    42         
    43     }
    44 
    45 }

    2.2、通过反射机制调用对象的某个方法。

     1 /**
     2  * 重点:通过反射机制调方法
     3  * @author yumu
     4  *
     5  */
     6 public class ReflectTest10 {
     7 
     8     /**
     9      * @param args
    10      * @throws Exception
    11      */
    12     /**
    13      * @param args
    14      * @throws Exception
    15      */
    16     public static void main(String[] args) throws Exception {
    17         //不使用反射机制,怎么调用方法
    18         UserService UserService=new UserService();
    19         boolean login = UserService.login("admin", "1213");
    20         //System.out.println(login ? "登录成功":"登录失败");
    21         
    22         //使用反射机制来调用一个对象的方法
    23         Class UserServiceClass=Class.forName("javase.service.UserService");
    24         
    25         //创建对象
    26         Object obj=UserServiceClass.newInstance();
    27         //获取Method
    28         @SuppressWarnings("unchecked")
    29         Method loginMethod=UserServiceClass.getDeclaredMethod("login",String.class,String.class);
    30         //调用方法有4要素
    31         //反射机制中最最最重要的内容,必须记住
    32         /*
    33          * 四要素:
    34          * loginMethod方法
    35          * opbj对象
    36          * "admin","123"实参
    37          * returnValue 返回值
    38          */
    39         Object returnValue = loginMethod.invoke(obj, "admin","123");
    40         System.out.println(returnValue);
    41     }
    42 
    43 }

    2.3、通过反射机制调用某个构造方法实例化对象。

     1 public class ReflectTest12 {
     2 
     3     public static void main(String[] args) throws Exception{
     4         //不使用反射机制怎么创建对象
     5         Vip v1=new Vip();
     6         Vip v2=new Vip(110,"张三","20200-10-10",true);
     7         System.out.println(v2);
     8         
     9         //使用反射机制怎么创建对象
    10         Class c=Class.forName("javase.bean.Vip");
    11         //调用无参数构造方法
    12         Object obj=c.newInstance();
    13         //调用有参数构造方法
    14         //第一步,先获取有参数构造方法
    15         Constructor con = c.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);
    16         Object obj1 = con.newInstance(110,"masan","1999-7-2",false);
    17         System.out.println(obj1);
    18         
    19         
    20     }
    21 
    22 }

    2.4、通过反射机制获取父类以及父类型接口。

     1 /**
     2  * 重点:获取父类,以及父类实现的接口
     3  * @author yumu
     4  *
     5  */
     6 public class ReflectTest13{
     7 
     8     public static void main(String[] args) throws Exception {
     9         //String 类举例
    10         Class stringClass=Class.forName("java.lang.String");
    11         //获取String父类
    12         Class superClass=stringClass.getSuperclass();
    13         System.out.println(superClass);
    14         
    15         //获取String类实现的所有接口
    16         Class [] interfaces =stringClass.getInterfaces();
    17         for(Class in : interfaces){
    18             System.out.println(in.getName());
    19             
    20         }
    21         System.out.println("-------------");
    22         System.out.println(interfaces);
    23     }
    24 
    25 }

    了解:

    1.反编译一个类的属性field

     1 **
     2  * 反射机制
     3  *  反编译一个类的属性field
     4  * @author yumu
     5  *
     6  */
     7 public class ReflectTest07 {
     8 
     9     public static void main(String[] args) throws ClassNotFoundException {
    10         StringBuilder sb=new StringBuilder();
    11         //获取整个类
    12         Class studentClass=Class.forName("javase.bean.Student");
    13         //                                       修饰符                                                                                                 //类名                       
    14         sb.append(Modifier.toString(studentClass.getModifiers())+" "+"class"+" "+studentClass.getSimpleName()+"{"+"
    ");
    15         //获取所有元素
    16         Field[] fields=studentClass.getDeclaredFields();
    17         for(Field field:fields){
    18             sb.append("	");
    19             //权限修饰符
    20             sb.append(Modifier.toString(field.getModifiers()));
    21             sb.append(" ");
    22             //数据类型
    23             sb.append(field.getType().getSimpleName());
    24             sb.append(" ");
    25             //数据名
    26             sb.append(field.getName());
    27             sb.append(";
    ");
    28         }
    29         sb.append("}");
    30         System.out.println(sb);
    31         
    32     }
    33 
    34 }
    反编译一个类的属性field

    2.反编译 Method

     1 /**
     2  * 反编译 Method
     3  * @author yumu
     4  *
     5  */
     6 public class ReflectTest09{
     7 public static void main(String[] args) throws Exception {
     8     StringBuilder s=new StringBuilder();
     9     //获取类
    10     Class UserServiceClass =Class.forName("java.lang.String");
    11     //                                        修饰符                                                                  //类名
    12     s.append(Modifier.toString(UserServiceClass.getModifiers())+"class"+UserServiceClass.getSimpleName()+"
    ");
    13     //获取所有的Method 包括私有的
    14     Method[] methods=UserServiceClass.getDeclaredMethods();
    15     //遍历Method
    16     for(Method method:methods){
    17         s.append("	");
    18         //获取修饰符列表
    19         s.append(Modifier.toString(method.getModifiers()));
    20         s.append(" ");
    21         //获取返回值类型
    22         s.append(method.getReturnType().getSimpleName());
    23         s.append(" ");
    24         //获取方法名
    25         s.append(method.getName());
    26         s.append("(");
    27         //参数列表
    28         Class[] parameterTypes=method.getParameterTypes();
    29         for(Class parameterType:parameterTypes){
    30             s.append(parameterType.getSimpleName());
    31             s.append(",");
    32             
    33         }
    34         //删除字符串最后一个
    35         s.deleteCharAt(s.length()-1);
    36         s.append("){}
    ");
    37             
    38     }
    39     s.append("}");
    40     System.out.println(s);
    41 }
    42 }
    反编译 Method

    3.反编译一个类的构造方法,costructor

    /**
     * 反编译一个类的构造方法,costructor
     * @author yumu
     *
     */
    public class ReflectTest11{
    
        public static void main(String[] args) throws Exception{
            StringBuilder s=new StringBuilder();
            Class vipClass=Class.forName("javase.bean.Vip");
            s.append(Modifier.toString(vipClass.getModifiers())+" ");
            s.append("class ");
            s.append(vipClass.getSimpleName());
            s.append("{
    ");
            //拼接构造方法
            //public Vip(int no, String name, String birth, boolean sex) {
            Constructor[] constructors = vipClass.getDeclaredConstructors();
            for(Constructor constructor:constructors){
                s.append("	");
                s.append(Modifier.toString(constructor.getModifiers()));
                s.append(" ");
                s.append(vipClass.getSimpleName());
                s.append("(");
                //拼接参数
                Class[] paramenterTypes=constructor.getParameterTypes();
                for(Class paramenterType:paramenterTypes){
                    s.append(paramenterType.getSimpleName());
                    s.append(",");
                    
                }
                if(paramenterTypes.length>0){
                    s.deleteCharAt(s.length()-1);
                }
                
                s.append("){}
    ");
                
            }
            
            s.append("}");
            
            System.out.println(s);
        }
    
    }
    反编译一个类的构造方法,costructor
  • 相关阅读:
    Magento:Paypal付款不成功返回后不要清空购物车产品的解决方案
    magento设置订单状态
    linux下查看所有用户以及用户组
    网站无法访问的原因
    magento 多域名多店铺
    linode空间lamp环境的搭建
    hp p410固件更新
    tracert
    镜像架设
    nohup
  • 原文地址:https://www.cnblogs.com/yumu77/p/13869305.html
Copyright © 2011-2022 走看看