zoukankan      html  css  js  c++  java
  • JAVA基础-反射机制

    什么是JAVA的反射机制

    Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其

    modifiers(诸如public, static等)、superclass(例如Object)、实现之

    interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行

    时改变fields内容或唤起methods。

    Java反射机制容许程序在运行时加载、探知、使用编译期间完全未知的classes。

    换言之,Java可以加载一个运行时才得知名称的class,获得其完整结构。

    反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。

    JAVA反射机制提供了什么功能

    Java反射机制提供如下功能:

    在运行时判断任意一个对象所属的类

    在运行时构造任意一个类的对象

    在运行时判段任意一个类所具有的成员变量和方法

    在运行时调用任一个对象的方法

    从接口 java.lang.reflect

    获取类的Class对象

    Class类的实例表示正在运行的Java应用程序中的类和接口。获取类的Class对象有多种方式:

    调用getClass:

    Boolean var1 = true;

    Class<?> classType2 = var1.getClass();System.out.println(classType2);

    输出:class java.lang.Boolean

    运用.class语法

    Class<?> classType4 = Boolean.class;

    System.out.println(classType4);

    输出:class java.lang.Boolean

    运用static methodClass.forName()

    Class<?> classType5= Class.forName("java.lang.Boolean");

    System.out.println(classType5);

    输出:class java.lang.Boolean

    运用primitive wrapper classes

    Class<?> classType3 = Boolean.TYPE;

    System.out.println(classType3);

    输出:boolean

    TYPE语法这里返回的是原生类型,和Boolean.class返回的不同

    public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
    // 方式1
    Person p = new Person();
    Class c = p.getClass();
    Person p2 = new Person();
    Class c2 = p2.getClass();
    System.out.println(p == p2);// false
    System.out.println(c == c2);// true
    // 方式2
    Class c3 = Person.class;
    // int.class;
    // String.class;
    System.out.println(c == c3);
    // 方式3
    // ClassNotFoundException
    Class c4 = Class.forName("cn.itcast_01.Person");
    System.out.println(c == c4);
    }
    }

    获取类的Fields

    可以通过反射机制得到某个类的某个属性,然后改变对应于这个类的某个实例的该属性值。

    JAVA的Class<T>类提供了几个方法获取类的属性。

    // 获取字节码文件对象
    Class c = Class.forName("cn.itcast_01.Person");
    // 获取单个的成员变量
    // 获取address并对其赋值
    Field addressField = c.getField("address");
    // public void set(Object obj,Object value)
    // 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
    addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
    System.out.println(obj);
    
    // 获取name并对其赋值
    // NoSuchFieldException
    Field nameField = c.getDeclaredField("name");
    // IllegalAccessException
    nameField.setAccessible(true);
    nameField.set(obj, "林青霞");
    System.out.println(obj);
    
    // 获取age并对其赋值
    Field ageField = c.getDeclaredField("age");
    ageField.setAccessible(true);
    ageField.set(obj, 27);
    System.out.println(obj);

    可见getFields和getDeclaredFields区别:

    getFields返回的是申明为public的属性,包括父类中定义,

    getDeclaredFields返回的是指定类定义的所有定义的属性,不包括父类的。

    获取类的Method

    通过反射机制得到某个类的某个方法,然后调用对应于这个类的某个实例的该方法

    Class<T>类提供了几个方法获取类的方法。

    getMethod

    public Method getMethod(String name,
                            Class<?>... parameterTypes)
                     throws NoSuchMethodException,
                            SecurityException
    class
    null
    public class ReflectDemo {
    public static void main(String[] args) throws Exception {
    // 获取字节码文件对象
    Class c = Class.forName("cn.itcast_01.Person");
    
    // 获取所有的方法
    // Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
    // Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法
    // for (Method method : methods) {
    // System.out.println(method);
    // }
      
    //创建新类的实例
    Constructor con = c.getConstructor();
    Object obj = con.newInstance();
    
    /*
     * Person p = new Person(); p.show();
     */
    
    // 获取单个方法并使用
    // public void show()
    // public Method getMethod(String name,Class<?>... parameterTypes)
    // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
    Method m1 = c.getMethod("show");
    // obj.m1(); // 错误
    // public Object invoke(Object obj,Object... args)
    // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
    m1.invoke(obj); // 调用obj对象的m1方法
    
    System.out.println("----------");
    // public void method(String s)
    Method m2 = c.getMethod("method", String.class);
    m2.invoke(obj, "hello");
    System.out.println("----------");
    
    // public String getString(String s, int i)
    Method m3 = c.getMethod("getString", String.class, int.class);
    Object objString = m3.invoke(obj, "hello", 100);
    System.out.println(objString);
    // String s = (String)m3.invoke(obj, "hello",100);
    // System.out.println(s);
    System.out.println("----------");
    
    // private void function()
    Method m4 = c.getDeclaredMethod("function");
    m4.setAccessible(true);
    m4.invoke(obj);
    }
    }
    

    获取类的Constructor

    通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例

    Class<T>类提供了几个方法获取类的构造器。

    //使用getConstructors获取构造器
    Constructor<?>[] constructors = classType.getConstructors();for(Constructor<?> m : constructors)
    {
    System.out.println(m);
    }
    //使用getDeclaredConstructors获取构造器
    constructors = classType.getDeclaredConstructors();
    for(Constructor<?> m : constructors)
    {
    System.out.println(m);
    }

    通过反射去获取该构造方法并使用

    public class ReflectDemo2 {
    public static void main(String[] args) throws Exception {
    // 获取字节码文件对象
    Class c = Class.forName("cn.itcast_01.Person");
    
    // 获取带参构造方法对象
    // public Constructor<T> getConstructor(Class<?>... parameterTypes)
    Constructor con = c.getConstructor(String.class, int.class,
    String.class);
    
    // 通过带参构造方法对象创建对象
    // public T newInstance(Object... initargs)
    Object obj = con.newInstance("林青霞", 27, "北京");
    
    System.out.println(obj);
    }
    }

    通过反射获取私有构造方法并使用

    public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {
    // 获取字节码文件对象
    Class c = Class.forName("cn.itcast_01.Person");
    
    // 获取私有构造方法对象
    // NoSuchMethodException:每个这个方法异常
    // 原因是一开始我们使用的方法只能获取公共的,下面这种方式就可以了。
    Constructor con = c.getDeclaredConstructor(String.class);
    
    // 用该私有构造方法创建对象
    // IllegalAccessException:非法的访问异常。
    // 暴力访问
    con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
    Object obj = con.newInstance("风清扬");
    
    System.out.println(obj);
    }
    }

    新建类的实例

    调用类的Class对象的newInstance方法

    该方法会调用对象的默认构造器,如果没有默认构造器,会调用失败.

    Class<?> classType = ExtendType.class;
    Object inst = classType.newInstance();
    System.out.println(inst);

    输出:

    Type:Default Constructor

    ExtendType:Default Constructor

    com.quincy.ExtendType@d80be3

    调用默认Constructor对象的newInstance方法

    Class<?> classType = ExtendType.class;
    Constructor<?> constructor1 =
    classType.getConstructor();
    Object inst = constructor1.newInstance();
    System.out.println(inst);

    输出:

    Type:Default Constructor

    ExtendType:Default Constructor

    com.quincy.ExtendType@1006d75

    调用带参数Constructor对象的newInstance方法

    Constructor<?> constructor2 =
    classType.getDeclaredConstructor(int.class,
    String.class);
    Object inst = constructor2.newInstance(1, "123");
    System.out.println(inst);

    输出:

    Type:Default Constructor

    ExtendType:Constructor with parameters

    com.quincy.ExtendType@15e83f9

  • 相关阅读:
    递归练习:走台阶
    递归练习:计算最大公约数和最小公倍数
    递归练习:逆序输出一个十进制数的各位数字
    m4, autoconf
    Makefile 和 CMakeLists.txt
    Java中的String pool
    小米路由Mini刷Breed, 潘多拉和LEDE
    Centos 编译LEDE/OpenWrt
    Centos6下编译安装gcc6.4.0
    IntelliJ IDEA遇到Unable to parse template “Class”错误
  • 原文地址:https://www.cnblogs.com/GitBoy/p/11093769.html
Copyright © 2011-2022 走看看