java_反射

反射:reflect   成员属性:Field  成员方法:Method 构造方法:Constructor  类:Class

引用,援引:invoke   新实例:newInstance  Declared:公开

什么是反射?

反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖并操作类中的方法,属性,构造方法等成员

是一种通过class文件对类中所有成员属性,构造方法,成员方法进行操作的方式,无论是什么权限都可以进行操作

什么是Class对象?

学习反射主要是操作Class对象,那么什么是Class对象?

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。

Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

class文件和Class是两个概念

也就是说,Class也是java语言中的一个类,程序运行时,会将class文件加载到内存并对该类进行解剖,解剖类时会获得很多的数据,有成员变量数据,成员方法数据,构造方法数据等,JVM为了方便管理这些类的数据,内部会为每一个加载到内存的class文件创建一个Class对象,这个Class对象目的就是用来封装解剖得到的所有该类的数据

操作Class对象即可获取对应类的数据

创建对象的五种方式:

  1. 直接new对象

String str=new String(“张三”);

  1. 如果类中有无参构造方法,可以使用该类对应的Class文件直接创建对象(反射)

Student s=Student.class.newInstance();

  1. 通过类的Class对象获取该类的构造方法,通过构造方法创建对象(反射)

Class s1=Student.class;

Constructor c1=c1.getConstructor();

Student s2=c1.newInstance();

  1. 通过反序列化获取对象
  2. 通过Clone….获取对象(了解)

反射有什么用,有什么应用的地方?

  1. 一种新的创建对象,操作对象的方式
  2. 可以降低程序的耦合度,降低程序的维护难度

举例说明:

通过反射比较常用的获取类对象的方式:

Class class=Class.forName(“包名.类名”);

通过类的全限命名(字符串类型)即可创建对象,可以将该字符串以键值对的形式存储到properties文件中,

如果类名改变,只需要修改properties配置文件即可

而通过new出来的对象,如果类名发生改变,则需要修改代码

  1. ssh(Spring,Struts,Hibernate)框架底层就使用了大量的反射

反射怎么使用?

先总结一下,通过反射可以获取类的构造方法(Constructor),成员属性(Field),成员方法(Method),针对操作公有数据和操作所有权限数据分开来说

操作公有数据:

获取构造方法:如果构造函数有参数在参数列表加上相应参数类型的class属性即可

Constructor getConstructor()

Constructor[] getConstructors()

获取成员属性:需要传入属性名称

Field getField(String name);

Field[] getFields();

获取成员方法:(通过方法名称和参数才能唯一标识一个方法,所以需要传入方法名称和参数)

Method getMethod(String methodName,参数…)

Method[] getMethods()

操作所有权限的数据

在操作公有数据基础上,get后面加上Declared,如果操作构造方法或者成员属性或者成员方法,先用方法对象或者属性对象调用setAccessible并且传入true即可

代码详解:

  

package com.ahd.lianxi;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class Demo01 {
public static void main(String[] args) throws Exception {
//练习反射 /*
* 获取Class对象的三种方式
* 方式一:通过对象调用getClass方法获取
*
* 方式二:通过类名的class属相获取
*
* 方式三:通过类的权限命名加载Class文件,需要抛出异常(这种方法比较常用)
* */
Student s=new Student("zhangsan");
Class<? extends Student> c1 = s.getClass(); Class<Student> c2 = Student.class; Class.forName("com.ahd.lianxi.Student"); /*
* 获取Class对象,可以通过该对象获取该对象相应的构造方法,成员属性
* ,成员方法,进而进行操作
* 首先说操作构造方法,创建对象
* Constructor<? extends Student> constructorC1 = c1.getConstructor();
* 该构造方法获取公有的构造方法,传入相应的参数表示获取对应的构造方法,
* Constructor<? extends Student> declaredConstructorC1 = c1.getDeclaredConstructor();
* 该构造方法获取所有权限的构造方法,传入相应的参数表示获取对应的构造方法,比较常用
* Constructor<?>[] constructors = c1.getConstructors();
* 该构造方法获取所有公有的构造方法,比较常用
* Constructor<?>[] declaredConstructors = c1.getDeclaredConstructors();
* 该构造方法获取所有权限的构造方法,
*
* 如果要通过无参构造方法创建对象,可以直接使用Class对象的newInstance方法获取相应对象
* Student student1 = c1.newInstance();
* */
Constructor<? extends Student> constructorC1 = c1.getConstructor();
Constructor<? extends Student> constructorC2 = c1.getConstructor(String.class);
Constructor<? extends Student> declaredConstructorC1 = c1.getDeclaredConstructor(); Constructor<?>[] constructors = c1.getConstructors();
Constructor<?>[] declaredConstructors = c1.getDeclaredConstructors();
//通过Declared获取的属性,方法..,需要先通过属性对象或者方法对象暴力破解一下
//declaredConstructorC1.setAccessible(true);
declaredConstructorC1.setAccessible(true);
//通过迭代器可以遍历所有构造方法,进行相应操作
//略... //使用构造方法创建对象
Student student = constructorC1.newInstance();
Student student2 = constructorC2.newInstance("赵四"); /*
* 通过Class对象获取成员属性
* Field field1 = c1.getField("username");
* 获取公有的指定属性名称的属性对象
* Field field2 = c1.getDeclaredField("username");
* 获取所有权限的指定属性名称的属性对象
* Field[] fields = c1.getFields();
* 获取公有的所有属性对象
* Field[] declaredFields = c1.getDeclaredFields();
* 获取所有权限的所有属性对象
* */
Field field1 = c1.getField("username");
Field field2 = c1.getDeclaredField("username");
//通过Declared获取的属性,方法..,需要先通过属性对象或者方法对象暴力破解一下
//field2.setAccessible(true);
field2.setAccessible(true); /*
* 对属性进行操作
* get方法获取属性的值: Object get(Object obj)
* 返回指定对象上此 Field 表示的字段的值。
* set方法为属性赋值:void set(Object obj, Object value)
* 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
* 个人理解:obj即该成员属性所属于的对象,value为为该属性赋的值
* */
field1.set(student,"lisi");
System.out.println(field1.get(student)); Field[] fields = c1.getFields();
Field[] declaredFields = c1.getDeclaredFields(); //通过迭代器可以遍历所有属性,进行相应操作
//略... /*
* 通过Class对象获取成员方法,获取成员方法需要传入方法名称和参数类型(类型是对应的class文件)
* ,方法获取后可以指定对象调用成员方法
* ,调用成员方法需要指定对象和参数列表(可变参数)
* public Method getMethod(String name,
* Class<?>... parameterTypes)
* 获取公有的成员方法
* Method declaredMethod = c1.getDeclaredMethod("getUsername");
* 获取所有权限的一个成员方法
* Method[] methods = c1.getMethods();
* 获取所有公有的成员方法
* Method[] declaredMethods = c1.getDeclaredMethods();
* 获取所有具有所有权限的成员方法
*
*
* */
Method method = c1.getMethod("getUsername");//调用无参方法,参数可以不写
Method declaredMethod = c1.getDeclaredMethod("getUsername");
//通过Declared获取的属性,方法..,需要先通过属性对象或者方法对象暴力破解一下
//declaredMethod.setAccessible(true);
declaredMethod.setAccessible(true); Method[] methods = c1.getMethods();
Method[] declaredMethods = c1.getDeclaredMethods(); System.out.println("##########################");
//方法调用
method.invoke(student);
System.out.println(method.invoke(student)); }
}

我有一句话想要对你说

地基越牢固,楼才能建的更高

笔者原创,欢迎大佬指出错误

上一篇:IISEXPRESS64位运行


下一篇:[hardware][intel] intel全系列网卡调研