• Java反射机制


    反射机制的基础:

    在Java中Object类是一切类的父类,因此所有类的对象实际上也就都是java.lang.Class类的实例,所有对象都可以转变为java.lang.Class类型表示。

    Class表示一个类的本身,通过Class可以完整地得到一个类中的完整结构,包括此类中的方法定义、属性定义等,常用操作如下:

    public static Class<?> forName(String className) throws ClassNotFoundException  传入完整的“包.类”名称实例化Class对象

    public Constructor[] getConstructors() throws SecurityException           得到一个类中的全部构造方法

    public Field[] getDeclaredFields[] throws SecurityException              得到本类中单独定义的全部属性

    public Field[] getFields() throws SecurityException                    取得本类继承而来的全部属性

    public Method[] getMethods() throws SecurityException                 得到一个类中的全部方法

    public Method getMethod(String name,Class...parameter Types) throws NoSuchMethodException, SecurityException    返回一个Method对象,并设置一个方法中的所有参数类型

    public Class[] getInterfaces()  得到一个类中所实现的全部接口

    public String getName()    得到一个类完整的“包.类”名称

    public Package getPackage()    得到一个类的包

    pubilc Class getSuperclass()    得到一个类的父类

    public Object newInstance()   根据Class定义的类实例人对象

    public Class<?> getComponentType()  返回表示数组类型的Class

    public boolean isArray()  判断此Class是否是一个数组

    实例化Class类对象的三种方法

    package com.yuchao.reflect;
    class X
    {

    }

    public class Reflection {

    /**
    *
    @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    Class<?> class1=null;
    Class
    <?> class2=null;
    Class
    <?> class3=null;

    try {
    class1
    =Class.forName("com.yuchao.reflect.X");
    }
    catch (ClassNotFoundException e) {
    // TODO: handle exception
    e.printStackTrace();
    }

    class2
    =new X().getClass();
    class3
    =X.class;
    System.out.println(
    "类名称:"+class1.getName());
    System.out.println(
    "类名称:"+class2.getName());
    System.out.println(
    "类名称:"+class3.getName());
    }

    }

    从程序的运行中可以发现,3种实例化Class对象的方法是一样的,但是使用forName()的静态方法实例化Class对象是较为常用的一种方式。

    Class类的使用

    Class类在开发中最常见的用法就是实例化对象的操作,即可以通过一个给定的字符串来实例化一个类的对象。

    通过无参构造实例化对象

    package com.yuchao.reflect;
    class Person
    {
    private String name;
    private int age;

    public String getName()
    {
    return this.name;
    }

    public void setName(String name)
    {
    this.name=name;
    }

    public int getAge()
    {
    return this.age;
    }

    public void setAge(int age)
    {
    this.age=age;
    }

    public String toString()
    {
    return "姓名:"+this.name+";"+"年龄:"+this.age;
    }
    }

    public class ClassInstance {

    /**
    *
    @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stubC
    Class<?> class1=null;
    try {
    class1
    =Class.forName("com.yuchao.reflect.Person");
    }
    catch (Exception e) {
    // TODO: handle exception
    e.printStackTrace();
    }
    Person person
    =null;
    try {
    person
    =(Person)class1.newInstance();
    }
    catch (Exception e) {
    // TODO: handle exception
    e.printStackTrace();
    }
    person.setName(
    "yuchao");
    person.setAge(
    25);
    System.out.println(person);
    }

    }

    程序运行结果:

    姓名:yuchao;年龄:25

    Class.forName()方法实例化Class对象之后,直接调用newInstance()方法就可以进行对象的实例化操作。但要注意的是,被实例化对象的类中必须存在无参构造方法,如果不存在则肯定是无法实例化的。在实际的Java程序开发中,反射是最为重要的操作原理,在现在的开发设计中大量地应用了反射处理机制,如Struts、Spring框架等;在大部分的操作中基本上都是操作无参构造方法,所以使用反射开发时类中尽量保留无参的构造方法。

    调用有参构造实例化的对象

    如果没有无参构造方法,就一定不能进行实例化对象操作吗?答案是否定的,只要在操作时明确地调用类中的构造方法,将参数传递进去同样可以进行实例化操作。操作步骤如下:

    1.通过Class类中的getConstructors()取得本类中的全部构造方法;

    2.向构造方法中传递一个对象数组进行,里面包含了构造方法中所需的各个参数;

    3.之后通过Constructor实例化对象

    package com.yuchao.reflect;

    import java.lang.reflect.Constructor;

    class Person
    {
    private String name;
    private int age;

    public Person(String name,int age)
    {
    this.name=name;
    this.age=age;
    }

    public String getName()
    {
    return this.name;
    }

    public void setName(String name)
    {
    this.name=name;
    }

    public int getAge()
    {
    return this.age;
    }

    public void setAge(int age)
    {
    this.age=age;
    }

    public String toString()
    {
    return "姓名:"+this.name+";"+"年龄:"+this.age;
    }
    }

    public class ClassInstance {

    /**
    *
    @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stubC
    Class<?> class1=null;
    try {
    class1
    =Class.forName("com.yuchao.reflect.Person");
    }
    catch (Exception e) {
    // TODO: handle exception
    e.printStackTrace();
    }
    Person person
    =null;
    Constructor
    <?> constructons[]=null;
    constructons
    =class1.getConstructors();
    try {
    //person=(Person)class1.newInstance();
    person=(Person)constructons[0].newInstance("yuchao",25);
    }
    catch (Exception e) {
    // TODO: handle exception
    e.printStackTrace();
    }
    System.out.println(person);
    }

    }

    程序运行结果:

    姓名:yuchao;年龄:25

    以上代码虽然已经完成了对象的实例化过程,但是代码比较复杂,因此在实际开发中尽量保留无参的构造函数。

    反射的应用-取得类的结构

    java.lang.reflect包中有以下几个类:Constructor、Field、Method

    通过以下几个类和Class类就可以共同完成类的反射操作。

    取得所实现的全部接口

    package com.yuchao.reflect;

    interface China
    {
    public static final String NATIONAL_STRING="China";
    public static final String AUTHOR_STRING="yuchao";
    public void sayChina();
    public String sayHello(String name,int age);
    }
    class Person implements China
    {
    private String name;
    private int age;

    public Person()
    {

    }

    public Person(String name,int age)
    {
    this.name=name;
    this.age=age;
    }

    public String getName()
    {
    return this.name;
    }

    public void setName(String name)
    {
    this.name=name;
    }

    public int getAge()
    {
    return this.age;
    }

    public void setAge(int age)
    {
    this.age=age;
    }

    public String toString()
    {
    return "姓名:"+this.name+";"+"年龄:"+this.age;
    }

    @Override
    public void sayChina() {
    // TODO Auto-generated method stub
    System.out.println("作者:"+AUTHOR_STRING+",国籍:"+NATIONAL_STRING);
    }

    @Override
    public String sayHello(String name, int age) {
    // TODO Auto-generated method stub
    return name+",你好!我今年"+age+"岁了!";
    }
    }

    public class ClassInstance {

    /**
    *
    @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stubC
    Class<?> class1=null;
    try {
    class1
    =Class.forName("com.yuchao.reflect.Person");
    }
    catch (Exception e) {
    // TODO: handle exception
    e.printStackTrace();
    }
    Class
    <?> class2[]=class1.getInterfaces();
    for(int i=0;i<class2.length;i++)
    {
    System.out.println(
    "实现的接口名称:"+class2[i].getName());
    }
    }

    }
    取得父类,只需将class1.getInterfaces()改成class1.getSuperClass()、class.getConstructors()、class1.getConstructors()[0].getModifiers()


  • 相关阅读:
    Python基本数据统计(二)---- 数据选择 & 简单统计与处理
    python2.7无法使用上下左右和backspace
    Python基本数据统计(一)---- 便捷数据获取 & 数据准备和整理 & 数据显示
    CentOS 6.5下安装NumPy、SciPy、Scikit-Learn
    hihocoder 1296 数论三·约瑟夫问题
    The 13th Zhejiang Provincial Collegiate Programming Contest
    hihocoder1181 欧拉路
    UPCOJ2985 Gopher(二分匹配)
    HNU13377 Book Club(二分匹配)
    HDU4799 LIKE vs CANDLE(树形dp)
  • 原文地址:https://www.cnblogs.com/yuchao/p/1966747.html
Copyright © 2020-2023  润新知