一、前言

1.1 Java程序运行流程

06.Java反射技术简介01-Java程序运行流程.png

相信大家在初学Java时都听过两个词:编译时异常和运行时异常。

编译时异常:在Java通过编译器由.Java文件编译成.class的字节码文件时出现的语法上的异常。

运行时异常:通过Java解释器加载进内存出现的如内存溢出、数组角标越界等异常。

1.2 正射和反射

正射:发生在Java代码编译时期,代码在编译时期就已经知道需要操作哪些类,以及调用类中的哪些方法。如果调用方法错误会在编译时期直接报错。

代码示例:

Student student = new Student(); //直接初始化,「正射」

student.setName("张三");

反射:运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。

总结:动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制

二、反射的概念

官方解析

Oracle 官方对反射的解释是:

Reflection is commonly used by programs which require the ability to examine or

modify the runtime behavior of applications running in the Java virtual machine.

This is a relatively advanced feature and should be used only by developers who

have a strong grasp of the fundamentals of the language. With that caveat in

mind, reflection is a powerful technique and can enable applications to perform

operations which would otherwise be impossible.

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

三、获取Class对象的三种方式

3.1使用Class.forName静态方法

 Class personClass = Class.forName("com.llc.blog.reflection.domain.Person");

3.2 使用类.class方法

Class personClass2 = Person.class;

3.3 使用实例对象的getClass()方法

Person person = new Person();

Class personClass3 = person.getClass();

完整代码:

public class relectionDemo {

    public static void main(String[] args) throws Exception {

        Class personClass = Class.forName("com.llc.blog.reflection.domain.Person");

        System.out.println(personClass.getName());

        Class personClass2 = Person.class;

        System.out.println(personClass2.getName());

        Person person = new Person();

        Class personClass3 = person.getClass();

        System.out.println(personClass3.getName());

    }

}

运行结果

com.llc.blog.reflection.domain.Person

com.llc.blog.reflection.domain.Person

com.llc.blog.reflection.domain.Person

四、反射API介绍

4.1 通过反射获取无参/有参构造方法

获取“公有”构造方法:

Constructor[] getConstructors():获取所有的"公有"构造方法;

public Constructor getConstructor(Class … parameterTypes):获取某个公有的构造方法

public class relectionDemo {

    public static void main(String[] args) throws Exception {

        Class personClass = Class.forName("com.llc.blog.reflection.domain.Person");

        //------------------------------获取公共构造方法----------------

        Constructor[] constructors = personClass.getConstructors();

        System.out.println("-------------遍历所有公共的构造方法---------");

        for(Constructor c: constructors){

            System.out.println(c);

        }

        System.out.println("--------------获取单个,公有,无参的构造方法,并调用---------------");

        Constructor constructor = personClass.getConstructor();//获取无参构造方法

        Object obj = constructor.newInstance();

        System.out.println("obj="+obj);

        System.out.println("--------------获取单个,公有,带参的构造方法,并调用--------------");

        constructor = personClass.getConstructor(String.class,String.class,String.class);

        Object obj2 = constructor.newInstance("张三", "27", "男");

        System.out.println("obj2="+obj2);

    }

}

运行结果

-------------遍历所有公共的构造方法---------

public com.llc.blog.reflection.domain.Person(java.lang.String,java.lang.String,java.lang.String)

public com.llc.blog.reflection.domain.Person()

--------------获取单个,公有,无参的构造方法,并调用---------------

obj=Person{name='null', age='null', sex='null'}

--------------获取单个,公有,带参的构造方法,并调用--------------

obj2=Person{name='张三', age='27', sex='男'}

获取“所有(包括私有)”构造方法:

Constructor[] getDeclaredConstructors()::获取所有的(包括私有的)构造方法;

public Constructor getDeclaredConstructor(Class… parameterTypes):获取某个构造方法(包括私有的)

public class relectionDemo04 {

    public static void main(String[] args) throws Exception {

        Class personClass = Class.forName("com.llc.blog.reflection.domain.Person");

        System.out.println("------------------------------获取所有的构造方法(包括私有)---------------");

        Constructor[] constructors = personClass.getDeclaredConstructors();

        for(Constructor c:constructors){

            System.out.println(c);

        }

        System.out.println("------------------------------获取所有的构造方法(包括私有),并调用---------------");

        Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class);

        declaredConstructor.setAccessible(true);//如果是私有的设置暴力访问,不然会出现IllegalAccessException异常

        Object instance = declaredConstructor.newInstance("张三");

        System.out.println(instance);

    }

}

运行结果

------------------------------获取所有的构造方法(包括私有)---------------

public com.llc.blog.reflection.domain.Person(java.lang.String,java.lang.String,java.lang.String)

private com.llc.blog.reflection.domain.Person(java.lang.String)

public com.llc.blog.reflection.domain.Person()

------------------------------获取所有的构造方法(包括私有),并调用---------------

Person{name='张三', age='null', sex='null'}

实体类

public class Person {

    private String name;

    private String age;

    private String sex;

    public Person() {

    }

    private Person(String name) {

        this.name = name;

    }

    public Person(String name, String age, String sex) {

        this.name = name;

        this.age = age;

        this.sex = sex;

    }

}

4.2 通过反射获取成员变量

获取公有的成员变量

Field[] getFields():获取所有公有的成员变量

Field getField():获取单个,公有的成员变量

public class relectionDemo {

    public static void main(String[] args) throws Exception {

        Class studentClass = Class.forName("com.llc.blog.reflection.domain.Student");

        System.out.println("----------------获取所有公有的成员变量-------------");

        Field[] fieldArray = studentClass.getFields();

        for(Field f : fieldArray){

            System.out.println(f);

        }

        System.out.println("----------------获取所有公有的成员变量,并赋值-------------");

        Field f = studentClass.getField("name");

        //赋值前,一定要确保堆中有"对象空间",所有要先创建一个对象

        Object obj = studentClass.getConstructor().newInstance();//调用公有无参的构造方法

        f.set(obj,"李林超博客");

        //验证

        Student stu = (Student)obj;

        System.out.println("Student的 name = " + stu.name);

    }

}

运行结果

----------------获取所有公有的成员变量-------------

public java.lang.String com.llc.blog.reflection.domain.Student.name

----------------获取所有公有的成员变量,并赋值-------------

Student的 name = 李林超博客

获取所有(包括私有)的成员变量

Field[] getDeclaredFields():获取所有成员变量(包括私有)

Field getDeclaredField():获取单个的成员变量,包括私有的

public class relectionDemo {

    public static void main(String[] args) throws Exception {

        Class studentClass = Class.forName("com.llc.blog.reflection.domain.Student");

        System.out.println("----------------获取所有的成员变量(包括私有)-------------");

        Field[] declaredFields = studentClass.getDeclaredFields();

        for(Field d:declaredFields){

            System.out.println(d);

        }

        System.out.println("----------------获取所有的成员变量(包括私有),并赋值-------------");

        Field address = studentClass.getDeclaredField("address");

        Object obj = studentClass.getConstructor().newInstance();//调用公有无参的构造方法

        address.setAccessible(true);//设置暴力访问

        address.set(obj,"北京市");

        //验证

        Student stu = (Student)obj;

        System.out.println("address = " + stu.getAddress());

    }

}

运行结果

----------------获取所有的成员变量(包括私有)-------------

public java.lang.String com.llc.blog.reflection.domain.Student.name

protected int com.llc.blog.reflection.domain.Student.age

char com.llc.blog.reflection.domain.Student.sex

private java.lang.String com.llc.blog.reflection.domain.Student.address

----------------获取所有的成员变量(包括私有),并赋值-------------

address = 北京市

为成员变量赋值:

Filed --> set(Object obj,Object value)

实体类

public class Student {

    public String name;

    protected int age;

    char sex;

    private String address;

    public String getAddress(){

        return this.address;

    }

}

4.3 通过反射调用成员方法

获取公有的成员方法

Method[] getMethods():获取所有公有的成员方法;

Method getMethod():获取单个公有的成员方法;

public class relectionDemo {

    public static void main(String[] args) throws Exception {

        Class studentClass = Class.forName("com.llc.blog.reflection.domain.Student");

        System.out.println("*****************************获取所有公有的成员方法*****************************");

        Method[] methodArray = studentClass.getMethods();//包含父类公有

        for(Method m:methodArray){

            System.out.println(m);

        }

        System.out.println("*****************************获取单个公有的,无参的并调用*****************************");

        Method m = studentClass.getMethod("show1");

        //实例化一个对象

        Object obj = studentClass.newInstance();

        m.invoke(obj);

        System.out.println("*****************************获取单个公有的,带参的,带返回值并调用*****************************");

        Method method = studentClass.getMethod("show2", String.class, int.class);

        Object result = method.invoke(obj, "张三", 20);//传递参数,并接受返回值

        System.out.println("返回值为:"+result);

    }

}

运行结果

*****************************获取所有公有的成员方法*****************************

public int com.llc.blog.reflection.domain.Student.show2(java.lang.String,int)

public void com.llc.blog.reflection.domain.Student.show1()

public final void java.lang.Object.wait() throws java.lang.InterruptedException

public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException

public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException

public boolean java.lang.Object.equals(java.lang.Object)

public java.lang.String java.lang.Object.toString()

public native int java.lang.Object.hashCode()

public final native java.lang.Class java.lang.Object.getClass()

public final native void java.lang.Object.notify()

public final native void java.lang.Object.notifyAll()

*****************************获取单个公有的,无参的并调用*****************************

公有的,无参的show1()方法......

*****************************获取单个公有的,带参的,带返回值并调用*****************************

公有 show2()方法:s = 张三 , n = 20

返回值为:1000

获取所有的成员方法包括私有

Method[] getDeclaredMethods():获取所有的成员方法包括私有的。

Method getDeclaredMethod():获取单个成员方法,包括私有的;

public class relectionDemo {

    public static void main(String[] args) throws Exception {

        Class studentClass = Class.forName("com.llc.blog.reflection.domain.Student");

      /*  System.out.println("*****************************获取所有公有的成员方法*****************************");

        Method[] methodArray = studentClass.getMethods();//包含父类公有

        for(Method m:methodArray){

            System.out.println(m);

        }

        System.out.println("*****************************获取单个公有的,无参的并调用*****************************");

        Method m = studentClass.getMethod("show1");

        //实例化一个对象

        Object obj = studentClass.newInstance();

        m.invoke(obj);

        System.out.println("*****************************获取单个公有的,带参的,带返回值并调用*****************************");

        Method method = studentClass.getMethod("show2", String.class, int.class);

        Object result = method.invoke(obj, "张三", 20);//传递参数,并接受返回值

        System.out.println("返回值为:"+result);*/

        System.out.println("*****************************获取所有的成员方法(包括私有的)*****************************");

        Method[] declaredMethods = studentClass.getDeclaredMethods();//不包含继承的;

        for(Method d:declaredMethods){

            System.out.println(d);

        }

        System.out.println("*****************************获取单个私有的,带参的并调用*****************************");

        Method method = studentClass.getDeclaredMethod("show5", int.class);

        Object obj = studentClass.newInstance();

        method.setAccessible(true);//暴力访问

        method.invoke(obj,20);

    }

}

运行结果

*****************************获取所有的成员方法(包括私有的)*****************************

public int com.llc.blog.reflection.domain.Student.show2(java.lang.String,int)

public void com.llc.blog.reflection.domain.Student.show1()

private void com.llc.blog.reflection.domain.Student.show5(int)

protected void com.llc.blog.reflection.domain.Student.show3(int)

void com.llc.blog.reflection.domain.Student.show4(int)

*****************************获取单个私有的,带参的并调用*****************************

私有的show5()方法:n = 20

调用方法:

Method --> public Object invoke(Object obj,Object… args)

实体类

public class Student {

    public void show1(){

        System.out.println("公有的,无参的show1()方法......");

    }

    public int show2(String s,int n){

        System.out.println("公有 show2()方法:s = " + s + " , n = " + n );

        return 1000;

    }

    protected void show3(int n){

        System.out.println("受保护的show3()方法:n = " + n);

    }

    void show4(int n){

        System.out.println("默认的show4()方法:n = " + n);

    }

    private void show5(int n){

        System.out.println("私有的show5()方法:n = " + n);

    }

}

五、获取Class对象对应的三个阶段

06.Java反射技术简介02--Java代码的三个阶段.bmp

Class.forName("全类名"):将字节码文件加载进内存,返回Class对象(Source源代码阶段)

   * 多用于配置文件,将类名定义在配置文件中。读取文件,加载类

类名.class:通过类名的属性class获取(Class类对象阶段)

   * 多用于参数的传递

对象.getClass():getClass()方法在Object类中定义着。(Runtime运行时阶段)

   * 多用于对象的获取字节码的方式

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

热门产品

php编程基础教程.pptx|php编程培训,php,编程,基础,教程,pptx
php编程基础教程.pptx

历史上的今天:04月16日

热门专题

安徽中源管业|安徽中源管业,安徽中源管业mpp电力管,安徽中源管业cpvc电力管,安徽中源管业pe穿线管,安徽中源管业电力管,安徽中源管业排水管,安徽中源管业通信管,安徽中源管业管材
安徽中源管业
大理科技管理学校|大理科技管理中等职业技术学校,大理市科技管理中等职业技术学校
大理科技管理学校
大理科技管理学校|大理科技管理学校,大理科技,大理科技中等职业技术学校,大理科技管理中等职业技术学校,大理科技学校
大理科技管理学校
金诺幼儿园(春城路金诺幼儿园)|昆明官渡区幼儿园,幼儿园报名,官渡区幼儿园,春城路幼儿园,幼儿园招生,学前班,昆明幼儿园,金诺幼儿园,环城南路幼儿园,石井路幼儿园
金诺幼儿园(春城路金诺幼儿园)
云南巨榕教育投资集团有限公司|云南巨榕教育投资集团有限公司,巨榕教育集团,巨榕教育
云南巨榕教育投资集团有限公司
一年制中专|中专学历,中专是什么学历,中专是什么,中专有什么专业,中专升大专,一年制中专
一年制中专
自考本科|自考本科有用吗,自考文凭,自考本科文凭,自考文凭有用吗,自考本科文凭有用吗,自考文凭承认吗
自考本科
天麻的功效与作用吃法|天麻的功效与作用,天麻的功效与作用吃法,天麻炖什么治头痛最好,天麻的功效与作用禁忌,天麻多少钱一斤,天麻的功效与作用吃法及禁忌,天麻怎么吃效果最好,天麻粉的功效与作用,天麻怎么吃
天麻的功效与作用吃法

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部