黑马程序员——Java基础---反射

来源:互联网 发布:2017网络水军招募 编辑:程序博客网 时间:2024/04/29 23:48

-----<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------


一.概述及作用

1.概述

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

2.反射的作用
反射的作用总结起来就一个:倒转了目标类和客户类的依赖关系。
以前我们设计程序,客户类要么依赖于目标类,要么依赖于目标类的接口。因为目标类是作为工具提供给客户类使用的,根据java 基本语法规则,要使用某个类,必须知道该类提供的接口。有了反射之后,我们就可以方便是使用反射来实现框架,解除框架对于我们写的类——目标类,的依赖关系。
反射的概念和实现原理
Reflection 是Java被视为动态(或准动态)语言的一个关键性质。反射就是把 JVM 通过符号引用动态解析 java 类的字节码的能力映射成为各种 Java 类的成分类的机制,通过这个机制,java 把 JVM 动态解析符号引用的功能封装为各种 API 类公开给我们使用,这个机制允许我们可以于运行时加载、探知、使用,编译期间完全未知的classes,程序在运行时通过 Reflection APIs 取得任何一个 class 的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现之interfaces(例如Serializable),也包括fields 和 methods 的所有信息,并可于运行时改变该类的对象的 fields 内容或调用该类或者该类对象的 methods。这种动态获取类的信息以及动态调用对象的方法的功能就是Java 语言的反射(Reflection)机制。

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

二.Java类反射中所必须的类:
Java的类反射所需要的类并不多,它们分别是:Class、Field、Constructor、Method、Object
.

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

三.举例详解

1.通过一个对象获得完整的包名和类名

<span style="white-space:pre"></span>package Reflect; <span style="white-space:pre"></span>/** <span style="white-space:pre"></span>* 通过一个对象获得完整的包名和类名 <span style="white-space:pre"></span>* */<span style="white-space:pre"></span>class Demo{    <span style="white-space:pre"></span>//other codes...<span style="white-space:pre"></span>} <span style="white-space:pre"></span>class hello{    <span style="white-space:pre"></span>public static void main(String[] args) {        Demo demo=new Demo();        System.out.println(demo.getClass().getName());    <span style="white-space:pre"></span>}<span style="white-space:pre"></span>}
【运行结果】:Reflect.Demo

2.实例化Class类对象

<span style="white-space:pre"></span>package Reflect;<span style="white-space:pre"></span>class Demo{    <span style="white-space:pre"></span>//other codes...<span style="white-space:pre"></span>} <span style="white-space:pre"></span>class hello{   <span style="white-space:pre"></span> public static void main(String[] args) {        Class<?> demo1=null;        Class<?> demo2=null;        Class<?> demo3=null;        try{            //一般尽量采用这种形式            demo1=Class.forName("Reflect.Demo");        }catch(Exception e){            e.printStackTrace();        }        demo2=new Demo().getClass();        demo3=Demo.class;                 System.out.println("类名称   "+demo1.getName());        System.out.println("类名称   "+demo2.getName());        System.out.println("类名称   "+demo3.getName());             <span style="white-space:pre"></span>}<span style="white-space:pre"></span>}<span style="white-space:pre"></span>

【运行结果】:

类名称   Reflect.Demo

类名称   Reflect.Demo

类名称   Reflect.Demo

3.通过Class实例化其他类的对象

1)通过无参构造实例化对象

package Reflect; class Person{         public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    @Override    public String toString(){        return "["+this.name+"  "+this.age+"]";    }    private String name;    private int age;} class hello{    public static void main(String[] args) {        Class<?> demo=null;        try{            demo=Class.forName("Reflect.Person");        }catch (Exception e) {            e.printStackTrace();        }        Person per=null;        try {            per=(Person)demo.newInstance();        } catch (InstantiationException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IllegalAccessException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        per.setName("Rollen");        per.setAge(20);        System.out.println(per);    }}

【运行结果】:

[Rollen  20]

2).通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)

package Reflect; import java.lang.reflect.Constructor; class Person{         public Person() {             }    public Person(String name){        this.name=name;    }    public Person(int age){        this.age=age;    }    public Person(String name, int age) {        this.age=age;        this.name=name;    }    public String getName() {        return name;    }    public int getAge() {        return age;    }    @Override    public String toString(){        return "["+this.name+"  "+this.age+"]";    }    private String name;    private int age;} class hello{    public static void main(String[] args) {        Class<?> demo=null;        try{            demo=Class.forName("Reflect.Person");        }catch (Exception e) {            e.printStackTrace();        }        Person per1=null;        Person per2=null;        Person per3=null;        Person per4=null;        //取得全部的构造函数        Constructor<?> cons[]=demo.getConstructors();        try{            per1=(Person)cons[0].newInstance();            per2=(Person)cons[1].newInstance("Rollen");            per3=(Person)cons[2].newInstance(20);            per4=(Person)cons[3].newInstance("Rollen",20);        }catch(Exception e){            e.printStackTrace();        }        System.out.println(per1);        System.out.println(per2);        System.out.println(per3);        System.out.println(per4);    }}
【运行结果】:
[null  0]
[Rollen  0]
[null  20]
[Rollen  20]

4.返回一个类实现的接口:

<span style="white-space:pre"></span>package Reflect; <span style="white-space:pre"></span>interface China{    public static final String name="Rollen";    public static  int age=20;    public void sayChina();    public void sayHello(String name, int age);} <span style="white-space:pre"></span>class Person implements China{    public Person() {             }    public Person(String sex){        this.sex=sex;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }    @Override    public void sayChina(){        System.out.println("hello ,china");    }    @Override    public void sayHello(String name, int age){        System.out.println(name+"  "+age);    }    private String sex;} <span style="white-space:pre"></span>class hello{    <span style="white-space:pre"></span>public static void main(String[] args) {    <span style="white-space:pre"></span>    Class<?> demo=null;        try{            demo=Class.forName("Reflect.Person");        }catch (Exception e) {            e.printStackTrace();        }        //保存所有的接口        Class<?> intes[]=demo.getInterfaces();        for (int i = 0; i < intes.length; i++) {            System.out.println("实现的接口   "+intes[i].getName());        }    }}

【运行结果】:实现的接口   Reflect.China

5.取得其他类中的父类

<span style="white-space:pre"></span>import java.lang.reflect.*;<span style="white-space:pre"></span>class hello{    <span style="white-space:pre"></span>public static void main(String[] args) {        Class<?> demo=null;        try{            demo=Class.forName("Reflect.Person");        }catch (Exception e) {            e.printStackTrace();        }        Constructor<?>cons[]=demo.getConstructors();        for (int i = 0; i < cons.length; i++) {            System.out.println("构造方法:  "+cons[i]);        }    }}

【运行结果】:

构造方法:  public Reflect.Person()

构造方法:  public Reflect.Person(java.lang.String)

6.通过class取得一个类的全部框架

<span style="white-space:pre"></span>class hello {    <span style="white-space:pre"></span>public static void main(String[] args) {        Class<?> demo = null;        try {            demo = Class.forName("Reflect.Person");        } catch (Exception e) {            e.printStackTrace();        }        System.out.println("===============本类属性========================");        // 取得本类的全部属性        Field[] field = demo.getDeclaredFields();        for (int i = 0; i < field.length; i++) {            // 权限修饰符            int mo = field[i].getModifiers();            String priv = Modifier.toString(mo);            // 属性类型            Class<?> type = field[i].getType();            System.out.println(priv + " " + type.getName() + " "                    + field[i].getName() + ";");        }        System.out.println("===============实现的接口或者父类的属性========================");        // 取得实现的接口或者父类的属性        Field[] filed1 = demo.getFields();        for (int j = 0; j < filed1.length; j++) {            // 权限修饰符            int mo = filed1[j].getModifiers();            String priv = Modifier.toString(mo);            // 属性类型            Class<?> type = filed1[j].getType();            System.out.println(priv + " " + type.getName() + " "                    + filed1[j].getName() + ";");        }    }}

【运行结果】:

===============本类属性========================

private java.lang.String sex;

===============实现的接口或者父类的属性========================

public static final java.lang.String name;

public static final int age;

7.通过反射取得并修改数组的信息

<span style="white-space:pre"></span>import java.lang.reflect.*;<span style="white-space:pre"></span>class hello{    <span style="white-space:pre"></span>public static void main(String[] args) {        int[] temp={1,2,3,4,5};        Class<?>demo=temp.getClass().getComponentType();        System.out.println("数组类型: "+demo.getName());        System.out.println("数组长度  "+Array.getLength(temp));        System.out.println("数组的第一个元素: "+Array.get(temp, 0));        Array.set(temp, 0, 100);        System.out.println("修改之后数组第一个元素为: "+Array.get(temp, 0));    <span style="white-space:pre"></span>}<span style="white-space:pre"></span>}

【运行结果】:

数组类型: int

数组长度  5

数组的第一个元素: 1

修改之后数组第一个元素为: 100





0 0