Java语法之反射

一、反射机制

在前面Java语法之注解自定义注解时我们也有提到反射,要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation对象。那什么是反射呢?JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。它有点类似照妖镜的作用,不管是什么妖魔鬼怪(类或对象)都能看到它的真面目(获取类的属性方法、调用对象的属性方法)。

二、Class理解

反射机制可以动态获取类信息以及调用对象方法,那它是通过什么实现的呢?这就要介绍下Class类了。首先明确Class也是一个类,只是它是一个描述类的类,它也可以生成对象。对于每个类而言,在JRE中有且仅有一个不变的 Class 类型的对象,而这个Class 类型的对象只能由系统建立,封装了当前对象所对应的类的信息,有哪些属性,方法,构造器,实现了哪些接口等等。而且每个类的实例都会记得自己是由哪个Class实例所生成。

那要获取类信息或调用对象方法,肯定首先要获取到该类或对象对应的Class类的实例。一般获取Class对象有三种方式。

1. 通过类名获取   类名.class

2. 通过对象获取   对象.getClass()

3. 通过全类名获取 Class.forName(全类名)

这里我们可以使用用字符串来做验证。输出结果都是class java.lang.String。

package Reflection;

public class ReflectionTest {

    public static void main(String[] args) throws ClassNotFoundException {
       //字符串的例子
       Class clazz = null;
       //类名.class
       clazz = String.class;
       System.out.println(clazz);
       //对象.getClass()
       clazz = "ReflectionTest".getClass();
       System.out.println(clazz);
       //Class.forName(全类名)
       clazz = Class.forName("java.lang.String");
       System.out.println(clazz);

    }

}
class java.lang.String
class java.lang.String
class java.lang.String

上面通过三种方式能获取到Class实例,然后再了解一下Class类常用的方法


方法名


功能说明


forName(String name)


返回指定类名 name 的 Class 对象


newInstance()


调用缺省构造函数,返回该Class对象的一个实例


newInstance(Object []args)


调用当前格式构造函数,返回该Class对象的一个实例


getName()


返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称


getSuperClass()


返回当前Class对象的父类的Class对象


getInterfaces()


获取当前Class对象的接口


getClassLoader()


返回该类的类加载器


getSuperclass()


返回表示此Class所表示的实体的超类的Class


getFields()


获取类中public类型的属性


getField(String name)


获取类特定的方法,name参数指定了属性的名称


getDeclaredFields()


获取类中所有的属性(public、protected、default、private),但不包括继承的属性


getDeclaredField(String name)


获取类特定的方法,name参数指定了属性的名称


getConstructors()


获取类中的公共方法


getConstructor(Class[] params)


获取类的特定构造方法,params参数指定构造方法的参数类型


getDeclaredConstructors()


获取类中所有的构造方法(public、protected、default、private)


getDeclaredConstructor(Class[] params)


获取类的特定构造方法,params参数指定构造方法的参数类型


getMethods()


获得类的public类型的方法


getMethod(String name, Class[] params)


获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型


getDeclaredMethods()


获取类中所有的方法(public、protected、default、private)


getDeclaredMethod(String name, Class[] params)


获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型

三、反射的使用

这里要着重介绍下上面API的使用,因为在后面要学习的Spring中IOC的原理就是反射加工厂模式。学好反射API有助于理解Spring框架内部实现。为了演示Class方法的使用,在注解demo的基础上对Person、Student类进行了修改。

Person类:

package Reflection;

@CustomDescription(description="基类")
@CustomDescription(description="人")
public class Person {

    private String Name;

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public String PersonPublicMethod(String str)
    {
        return str;
    }

    public Person(String name) {
        Name = name;
    }

    public String PersonPrivateMethod(String str)
    {
        return str;
    }

    public Person() {
        super();
    }

}

Student类:

package Reflection;

@CustomDescription(description="学生")
@CustomDescription(description="人")
public class Student extends Person {
    public String StudentId;

    public String getStudentId() {
        return StudentId;
    }

    public void setStudentId(String studentId) {
        StudentId = studentId;
    }

    public String StudentPublicMethod(String str)
    {
        return str;
    }

    private String StudentPrivateMethod(String str)
    {
        return str;
    }

    public Student(String name, String studentId) {
        super(name);
        StudentId = studentId;
    }

    public Student() {

    }
}

一、描述方法Method

描述方法的主要是4个获取方法getMethods、getMethod、getDeclaredMethods、getDeclaredMethod和1个调用方法invoke。
getMethods:获取clazz对应类中的所有方法,不能获取private方法,且获取从父类继承来的所有方法包括私有父类的私有方法
getMethod:获取clazz对应类中指定方法名和参数类型的方法,不能获取private方法,且获取从父类继承来的所有方法包括私有父类的私有方法,因为存在同方法名不同参数这种情况,所以只有同时指定方法名和参数类型才能唯一确定一个方法。
getDeclaredMethods:获取所有方法,包括私有方法,所有声明的方法,都可以获取到,且只获取当前类的方法。
getDeclaredMethod:获取clazz对应类中指定方法名和参数类型的方法,包括私有方法,所有声明的方法,都可以获取到,且只获取当前类的方法。
Invoke:执行方法,第一个参数表示执行哪个对象的方法,剩下的参数是执行方法时需要传入的参数,私有方法的执行,必须在调用invoke之前加上一句method.setAccessible(true);

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        Class clazz = Class.forName("Reflection.Student");
        Method method=null;
        Method[] methods=null;

        methods = clazz.getMethods();
        for(Method mth:methods){
            System.out.print(mth.getName()+" ");
        }
        System.out.println();

        method = clazz.getMethod("StudentPublicMethod",String.class);
        System.out.print(method.getName()+" ");
        System.out.println();

        methods = clazz.getDeclaredMethods();
        for(Method mth:methods){
            System.out.print(mth.getName()+" ");
        }
        System.out.println();

        method = clazz.getDeclaredMethod("StudentPrivateMethod",String.class);
        System.out.print(method.getName()+" ");
        System.out.println();

        Object obje = clazz.newInstance();
        method.setAccessible(true);
        String result=(String) method.invoke(obje,"inputParams");
        System.out.println(result);
    }

输出结果:

StudentPublicMethod setStudentId getStudentId getName setName PersonPrivateMethod PersonPublicMethod wait wait wait equals toString hashCode getClass notify notifyAll
StudentPublicMethod
StudentPrivateMethod StudentPublicMethod setStudentId getStudentId
StudentPrivateMethod
inputParams

二、描述字段Filed
描述字段Filed方法的使用和描述方法Method中方法的使用有点类似,也是4个获取字段的方法:getFields、getField、getDeclaredFields、getDeclaredField。
getFields:获得某个类的所有的公共(public)的字段,包括父类中的字段。
getField:获取某个类public成员变量中指定变量名的字段,包括基类。
getDeclaredFields:获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
getDeclaredField:获取某个类的所有成员变量指定变量名的字段,不包括基类。

1.字段获取

        Class clazz = Class.forName("Reflection.Student");
        System.out.println("---------getDeclaredFields---------");
        Field[] fields = clazz.getDeclaredFields();
        for(Field field: fields){
            System.out.print(field.getName()+" ");
        }
        System.out.println();
        System.out.println("---------getFields---------");
        fields = clazz.getFields();
        for(Field field: fields){
            System.out.print(field.getName()+" ");
        }
        System.out.println();

        System.out.println("---------getDeclaredField---------");
        Field field = clazz.getDeclaredField("StudentId");
        field.setAccessible(true);
        System.out.println(field.getName());

        System.out.println("---------getField--------");

        field = clazz.getField("StudentId");
        System.out.println(field.getName());
---------getDeclaredFields---------
StudentId
---------getFields---------
StudentId
---------getDeclaredField---------
StudentId
---------getField--------
StudentId

2.字段的使用

    Class clazz = Class.forName("Reflection.Person");
    Person person = new Person("CYW");
        //获取私有字段的值
        Field field = clazz.getDeclaredField("Name");
        //由于是私有字段,需要使用setAccessible(true)
        field.setAccessible(true);
        Object val = field.get(person);
        System.out.println(val);
        //改变私有字段的值
        field.set(person, "ivan");
        System.out.println(person.getName());

计划在未来6个月内写一本Spring入门的书,本篇和Java语法注解篇都是书的一部分,博友有什么建议或意见可以留言,我也好在后面的章节进行改进。未完,待续!

原文地址:https://www.cnblogs.com/5ishare/p/9452264.html

时间: 2024-08-05 11:55:52

Java语法之反射的相关文章

Java基础学习笔记二十三 Java核心语法之反射

类加载器 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,链接,初始化三步来实现对这个类进行初始化. 加载就是指将class文件读入内存,并为之创建一个Class对象.任何类被使用时系统都会建立一个Class对象. 链接指的是将Java类的二进制代码合并到JVM的运行状态之中的过程.在链接之前,这个类必须被成功加载.类的链接包括验证.准备和解析等几个步骤. 验证:是否有正确的内部结构,并和其他类协调一致. 准备:负责为类的静态成员分配内存,并设置默认初始化值 解析:

Java中的反射机制

Java反射的概念 Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制 Java反射机制主要提供下面几种用途: 1.在运行时判断任意一个对象所属的类 2.在运行时构造任意一个类的对象 3.在运行时判断任意一个类所具有的成员变量和方法 4.在运行时调用任意一个对象的方法 首先看一个简单的例子,通过这个例子来理解Java的反射机制是如何工作的 i

java语法糖

语法糖 Java语法糖系列,所以首先讲讲什么是语法糖.语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的字节码或者特定的方式对这些语法做一些处理,开发者就可以直接方便地使用了.这些语法糖虽然不会提供实质性的功能改进,但是它们或能提高性能.或能提升语法的严谨性.或能减少编码出错的机会.Java提供给了用户大量的语法糖,比如泛型.自动装箱.自动拆箱.foreach循环.变长参数.内部类.枚举类.断言(assert)等 断言(as

Java语言的反射机制 笔记 摘自 http://blog.csdn.net/kaoa000/article/details/8453371

在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的.这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制. 1.Java 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类.在运行时构造任意一个类的对象.在运行时判断任意一个类所具有的成员变量和方法.在运行时调用任意一个对象的方法 2.Reflection 是Java被视为动态(或准动态)语言的一个关键性质.

Java中的反射机制(一)

基本概念 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法? 答案是肯定的. 这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制. Java反射机制主要提供了以下功能: 1.在运行时判断任意一个对象所属的类. 2.在运行时构造任意一个类的对象. 3.在运行时判断任意一个类所具有的成员变量和方法. 4.在运行时调用任意一个对象的方法. Reflection是Java被视为动态(或准动

黑马程序员----Java高新技术之反射学习总结

------- android培训.java培训.期待与您交流! ---------- 反射的概念. 1.Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 精妙的总结就是:反射就是将Java类中的各个成分映射成相应的Java类. 3.在Java中,描述事物的各种类同样也是一种事物,也可以用面向对象的方法来描述,即也有一个类来描述众多的J

java中的反射机制(一)-----转载

Java 反射机制 基本概念 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法? 答案是肯定的. 这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制. Java反射机制主要提供了以下功能: 1.在运行时判断任意一个对象所属的类. 2.在运行时构造任意一个类的对象. 3.在运行时判断任意一个类所具有的成员变量和方法. 4.在运行时调用任意一个对象的方法. Reflection是Jav

Java语法糖设计

语法糖 Java语法糖系列,所以首先讲讲什么是语法糖.语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的字节码或者特定的方式对这些语法做一些处理,开发者就可以直接方便地使用了.这些语法糖虽然不会提供实质性的功能改进,但是它们或能提高性能.或能提升语法的严谨性.或能减少编码出错的机会.Java提供给了用户大量的语法糖,比如泛型.自动装箱.自动拆箱.foreach循环.变长参数.内部类.枚举类.断言(assert)等 断言(as

黑马程序员【java中的反射机制】

Java中的反射机制 ------- android培训.java培训.期待与您交流! ---------- java的反射机制是java的特性之一,反射机制是构建框架技术的基础所在,使用反射可以使程序更加灵活,避免将程序写死在代码里.相对于很多初学者只接触过java基础的人,反射还是一个很朦胧难懂的概念,下面我们就来说一下反射的一些应用. java反射机制是指在运行状态中,动态获取信息以及动态调用对象方法的功能.java反射有3个动态性质:1.运行时生成对象实例,2.运行期间调用发放,3.运行