zoukankan      html  css  js  c++  java
  • 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()


  • 相关阅读:
    mysql 历史版本下载
    mysql 5.7 版本 You must reset your password using ALTER USER statement before executing this statement报错处理
    5.7 zip 版本的安装 以及遇到的坑
    mysql 5.6zip版本的卸载与5.7 zip 版本的安装
    mysql数据库的备份与还原
    本地Navicat连接docker里的mysql
    docker修改数据库密码
    docker 在push镜像到本地registry出现的500 Internal Server Error
    linux 没有界面内容显示不全解决办法
    json与map互相转换
  • 原文地址:https://www.cnblogs.com/yuchao/p/1966747.html
Copyright © 2011-2022 走看看