Java的反射机制

什么是反射

Java的反射指的是在程序运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。并且对于每一个对象,我们都能够对它的属性和方法进行调用。 我们把这种动态调用对象属性对象方法的功能称为反射机制。


反射的三种方式

所谓的反射其实是根据类的字节码文件来获取属性和方法的,也就是.class文件,所以我们就是通过Class对象来获取这些属性和方法。

而反射一共有三种方式来来获取属性和方法。

1. 第一种方式:

Class  getClass() 返回此Object的运行时类

这个方法是来自Object的方法,Class继承了Object,所以我们可以直接使用这个方法。

//创建一个对象

Student student =new Student();

//获取对象的Class属性

Class c = student.getClass();

//获取类名称

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

2.第二种方式

第二种方式获取和第一种方式类似,可以直接通过类名直接获取class文件

Class c1 = Student.class;

//获取类名称

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

3.第三种方式

通过类的全路径名获取Class对象,但是这样获取,需要抛出一个ClassNotFoundException异常,如果在指定路径下找不到该类,就会抛出异常。

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

Class c2 = Class.forName("demo.demo.Student");

//获取类名称

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

}

一般会选择第三种方式获取类的class文件。


通过反射获取类的构造方法、方法以及属性

1.获取构造方法

可以通过Class的四个方法来获得类的构造方法

getConstructors()  (获得所有公用的构造方法)

getConstructor()  (获得公有的 & 无参的构造方法)

getDeclaredConstructors () (获得所有的构造方法)

getDeclaredConstructor() (获得私有 & 有参的构造方法)

需要抛出一个NoSuchMethodException异常,当没找到相应构造方法是抛出。

具体使用方法如下所示:

public static void main(String[] args)throws ClassNotFoundException, NoSuchMethodException {

//加载Class对象

    Class c = Class.forName("demo.demo.Student");

System.out.println("获得所有公用的构造方法!");

//获得所有的公用构造方法

    Constructor[] constructors = c.getConstructors();

for (Constructor constructor: constructors

) {

System.out.println(constructor);

}

System.out.println("获得所有的构造方法!");

//获得所有的构造方法

    Constructor[]  constructors1 = c.getDeclaredConstructors();

for (Constructor constructor: constructors1

){

System.out.println(constructor);

}

System.out.println("获得所有的公有 & 无参的构造方法");

//获得所有的公有 & 无参的构造方法

//传入null参数,获取无参的构造方法

    Constructor constructor2 = c.getConstructor(null);

System.out.println(constructor2);

System.out.println("获取所有的公有 & 有参的构造方法");

//获取所有的公有 & 有参的构造方法

//按照构造方法参数顺序,依次传入构造方法参数的类型,获取公有的有参构造方法

    Constructor constructor3 = c.getConstructor(new Class[]{int.class,String.class,String.class});

System.out.println(constructor3);

System.out.println("获取所有的私有 & 有参的构造方法");

//获取所有的私有 & 有参的构造方法

//方式与获取公有有参方法的方式类似,只是使用的类方法不一样

    Constructor constructor4 = c.getDeclaredConstructor(new Class[]{String.class});

System.out.println(constructor4);

}

运行结果如下所示:

Java的反射机制_第1张图片

2.获取类属性

获取类属性可以通过两个方法获取:

getField (获取公用字段)

getDeclaredField (获取私有字段,公用字段)

并且有一点需要注意的是,在获取私有字段赋值使用的过程中,需要进行暴力反射。

也就是需要暂时的关闭Java的权限检查机制,不再检查私有属性的访问权限,可以让我们给私有属性赋值。

使用 Filed.setAccessible(true) 方法来设置

https://www.cnblogs.com/fanguangdexiaoyuer/p/6548171.html(关于setAccessible方法更详细内容)

使用这两个方法需要抛出一个 NoSuchFieldException 异常,在类中找不到相应的字段时抛出。

具体使用方法如下:

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

//加载Class对象

    Class c = Class.forName("demo.demo.Student");

System.out.println("获取所有的公有字段!");

Field[] fields = c.getFields();

for (Field field : fields) {

System.out.println(field);

}

System.out.println("获取所有的字段(公有,私有)!");

Field[] fields1 = c.getDeclaredFields();

for (Field field : fields1) {

System.out.println(field);

}

System.out.println("获取公有字段并赋值使用!");

//获取指定公有字段

    Field field = c.getField("name");

//获取一个公有构造方法,并且使用newInstance方法实例化。

    Object obj = c.getConstructor().newInstance();

//为属性设置值

    field.set(obj,"kk");

Student student = (Student)obj;

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

System.out.println("获取私有字段并赋值使用!");

//获取指定私有字段

    Field field1 = c.getDeclaredField("address");

//获取一个公有构造方法,并且使用newInstance方法实例化。

    Object obj1 = c.getConstructor().newInstance();

//暴力反射,关闭Java 语言访问控制检查的能力,禁用安全检查,也就是暂时关闭私有权限的访问权限。

    field1.setAccessible(true);

//为属性设置值

    field1.set(obj1,"kkAddress");

Student student1 = (Student)obj1;

System.out.println(student1.getAddress());

}

运行结果如下所示:


Java的反射机制_第2张图片

3.获取指定方法并使用

获取类的方法可以通过两个方法来获取

getMethod(获取公有方法)

getDeclaredMethod(获取公有方法、私有方法、受保护方法)

先定义几个不同类型的方法:

public void method() {

System.out.println("公用无参方法");

}

public void method(String name) {

System.out.println("公用有参方法");

}

protected void method2(String name) {

System.out.println("受保护有参方法");

}

private void method1() {

System.out.println("私有无参方法");

}

public void OutStudent(int age,String name,String address){

System.out.println("公用有参方法");

System.out.println("学生信息:" + age + name + address);

}

然后具体使用方法如下:

//加载Class对象

Class c = Class.forName("demo.demo.Student");

System.err.println("获取所有的public修饰的方法");

Method[] methods = c.getMethods();

for (Method method : methods) {

System.out.println(method);

}

Thread.sleep(1000);

System.err.println("获取所有的方法");

Method[] methods1 = c.getDeclaredMethods();

for (Method method:methods1

) {

System.out.println(method);

}

Thread.sleep(1000);

System.err.println("获取指定方法(不带参)并使用");

Method method = c.getDeclaredMethod("method");

System.out.println(method);

Thread.sleep(1000);

System.err.println("获取指定方法(带参)并使用");

Method method1 = c.getMethod("method",String.class);

System.out.println(method1);

Thread.sleep(1000);

System.err.println("获取指定方法(多个参数)并使用");

Method method2 = c.getDeclaredMethod("OutStudent",int.class, String.class, String.class);

//获取构造方法,实例化一个对象

Object object = c.getConstructor().newInstance();

//给指定方法传值

//使用invoke调用指定方法

method2.invoke(object,18,"kk","address");

运行结果如下所示:


Java的反射机制_第3张图片

你可能感兴趣的:(Java的反射机制)