• java笔记十:java中的反射


      Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。

      Java的类反射所需要的类并不多,它们分别是:Field、Constructor、Method、Class、Object,下面我将对这些类做一个简单的说明。
    Field类:提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。
    Constructor类:提供关于类的单个构造方法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,而Constructor类则封装了反射类的构造方法。
    Method类:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 这个类不难理解,它是用来封装反射类方法的一个类。
    Class类:类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
    Object类:每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

      下面举几个例子:

    ①、反射类中的属性

     1 package com.reflect;
     2 
     3 import java.awt.event.ActionEvent;
     4 import java.awt.event.ActionListener;
     5 import java.lang.reflect.Field;
     6 
     7 class A extends Object implements ActionListener{
     8     public String s = "aaa";
     9     private int a = 3;
    10     private Integer b = new Integer(4);
    11     public A(){}
    12     public A(int id,String name){}    
    13     private int abc(int id,String name){
    14         return 0;
    15     }
    16     public void actionPerformed(ActionEvent e) {
    17         System.out.println("actionPerformed()");
    18     }
    19     public void f1(int a){System.out.println(a);}
    20     private void f2(int a){
    21         System.out.println(a);
    22     }
    23 }
    24 
    25 public class TestReflect {
    26     public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    27         A a = new A();
    28         Class c = a.getClass();
    29         //反射属性
    30         Field[] fields = c.getFields();//得到公有属性
    31         //Field[] fields = c.getDeclaredFields(); //得到所有属性
    32         for (int i = 0; i < fields.length; i++) {
    33             Class c1 = fields[i].getType(); //得到属性类型
    34             System.out.println(c1);
    35         }
    36         System.out.println("反射类中的私有属性");
    37         Field f = c.getDeclaredField("a");
    38         f.setAccessible(true);  //如果是私有成员,则要加这句,否则无法访问
    39         System.out.println(f.get(a));//f.get(o)返回o对象的f属性
    40     }
    41 
    42 }

      反射类中的属性主要有两个方法:getFields()和getDeclaredFielda(),这两个方法返回的都是一个Field数组。getFields()得到的是public修饰的属性,而getDeclaredFielda()得到的是所有的属性。当然也可以得到某一个属性,如Field f = c.getDeclaredField("a"),如果该属性是私有的话,必须加上f.setAccessible(true),否则用到的时候会报java.lang.IllegalAccessException异常。

    ②、反射类中的构造方法

     1 package com.reflect;
     2 
     3 import java.lang.reflect.Constructor;
     4 
     5 public class RefectConstructors {
     6     public static void main(String[] args) throws NoSuchMethodException, SecurityException {
     7         Class c = A.class;
     8         String className = c.getName();//得到类名
     9         Constructor[] cons = c.getConstructors();  //得到所有构造方法
    10         for (int i = 0; i < cons.length; i++) {
    11             Class[] parameterTypes = cons[i].getParameterTypes();
    12             System.out.print(className+"(");
    13             for (int j = 0; j < parameterTypes.length; j++) {
    14                 System.out.print(parameterTypes[j].getName()+" ");
    15             }
    16             System.out.print(")");
    17             System.out.println();
    18         }
    19         Constructor con = c.getConstructor(int.class,String.class);  //得到某个具体的构造方法
    20         System.out.println(con.getName());
    21     }
    22 
    23 }

      通过反射得到某个类的构造方法可以通过c.getConstructors()来获得,返回的是Constructor数组,也可以用c.getConstructor(Class ...)方法来获得某个具体构造方法这个方法的参数是构造方法的参数类class对象。

    ③、反射接口和父类

     1 package com.reflect;
     2 
     3 public class ReflectInterface {
     4 
     5     public static void main(String[] args) {
     6         Class c = A.class;
     7         //反射得到所有的接口
     8         Class[] interfaces = c.getInterfaces();
     9         for (int i = 0; i < interfaces.length; i++) {
    10             System.out.println(interfaces[i].getName());
    11         }
    12         //反射得到所有的父类
    13         Class superClass = c.getSuperclass();
    14         System.out.println(superClass.getName());
    15     }
    16 }

    ④、反射得到方法

     1 package com.reflect;
     2 
     3 import java.lang.reflect.InvocationTargetException;
     4 import java.lang.reflect.Method;
     5 
     6 public class ReflectMethod {
     7     public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
     8         Class c = A.class;
     9         A a = new A();
    10         //Method[] methods = c.getDeclaredMethods();  //返回该类定义的所有方法。父类的方法若没有被重写则不会返回
    11         Method[] methods = c.getMethods();  //得到public方法,包括从父类继承的方法
    12         for (int i = 0; i < methods.length; i++) {
    13             //输出方法的返回类型
    14             System.out.print(methods[i].getReturnType());
    15             //输出方法名
    16             System.out.print(" "+methods[i].getName()+"(");
    17             //获取方法的参数
    18             Class[] paramTypes = methods[i].getParameterTypes();
    19             for (int j = 0; j < paramTypes.length; j++) {
    20                 System.out.print(paramTypes[j].getName());
    21                 if(paramTypes.length>j+1){
    22                     System.out.print(",");
    23                 }
    24             }
    25             System.out.print(")");
    26             System.out.println();
    27         }
    28         //得到指定私有方法名
    29         Method m = c.getDeclaredMethod("f2",int.class); //方法名、方法中的参数
    30         //私有方法需要让其能够被访问
    31         m.setAccessible(true);
    32         m.invoke(a, 5);
    33     }
    34 
    35 }

      c.getDeclaredMethods():返回该类定义的所有方法。父类的方法若没有被重写则不会返回。

      c.getMethods(): 得到所有public方法,包括从父类继承的方法

      c.getDeclaredMethod(String methodName,Class param) :得到某个具体的方法,要传入方法名和方法的参数。

  • 相关阅读:
    我开发中的用到的几个框架
    关于ASP.NETCore的分享之学习路线
    首个.NET5+Vue.js业务模块化快速开发框架【NetModular】发布
    [C#] (原创)一步一步教你自定义控件 —— 系列文章
    EFS加密
    博客园样式美化:给博客添加一个音乐播放器
    XSS语义分析
    TCP回放攻击 & DDoS脉冲攻击Hit and Run IoT僵尸网络 在DDoS攻击黑产领域最活跃
    小样本学习,阿里做得比较早,但是效果未知——小样本有3类解决方法(算法维度):迁移学习、元学习(模型基础上学习模型)、度量学习(相似度衡量,也就是搜索思路),数据维度还有GAN
    真实世界中的开集识别问题(Open-Set Recognition Problem)——Walter J. Scheirer研究是最深的,安全里已经有研究了,但是感觉只是触及了皮毛而已
  • 原文地址:https://www.cnblogs.com/liuling/p/reflect.html
Copyright © 2020-2023  润新知