反射的概念:
1.Class类的引出
* 一切皆对象,用类来描述一般对象,但用什么来描述类这个对象呢?
* eg: Date d=new Date(),用什么类来描述Date这个类呢?
* 引入 Class类
* Class
* Class
*
* 当程序第一次把使用某一个java.utile.Date类的时候就会把该类的字节码对象加载进JVM
* 并创建出一个Class对象,此时的Class对象就是java.utile.Data的字节码
2.获取Class类实例的三种方法
* //方式1.class属性
* //方式2.通过对象的getClass()方法来获取,getClass是object中的方法
* //方式3.通过Class类中的静态方法forname(String ClassName)
*
* 方式2和方式3经常用,尤其是方式3在框架中用的很多
实例如图:
3.通过反射去获取构造器
* 需求:通过反射来获取某一个类的构造器
* 1).获取该类的字节码对象
* 2).从该类的字节码对象中去找需要获取的构造器
*
* Class类获取所有构造器的方法:
* Constructor类; 表示类中构造器的类型,Constructor的实例是某一个类中的构造器
*
* public Constructor>[] getConstructor();该方法只能获取当前Class表示类的public修饰的构造器
* public Constructor>[] getDeclaredConstructor();获取当前Class表示类中的所有构造器和访问权限无关
*
*
* Class类获取指定构造器的方法:
* public Constructor
* 参数:parameterYypes表示:构造器参数的Class类型,即字节码对象
*
* eg: public User(String name)
* Constructor c=clz.getConstructor(String.class)
*
* public Constuctor
4.使用反射调用构造器创建对象
* 使用反射创建对象
* 步骤:
* 1):找到构造器所在类的字节码对象
* 2):获取构造器对象
* 3):使用反射,创建对象
*
* Constructor<>类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器
* 常用方法:
* public T newInstance(Object...initargs):如果调用带参数的构造器,只能使用该方式
* 参数:initargs表示调用构造器的实际参数
* 返回:返回创建的实例,T表示Class所表示类的类型
*/
// 如果一个类中的构造器可以直接访问,同时没有参数,那么直接使用Class类中的newInstance()方法创建对象
//访问私有的成员,必须将其设置为可访问的
//对象.setAccessible(true)
5.九大内置Class实例
* 有是三种获取Class对象的方法,但是基本数据类型不能表示为对象,也就不能使用getClass的方式
* 基本类型没有类名的概念,而且也不能使用Class.forname(String className)方式获取Class对象
*
* 问题:那么如何获取基本数据类型的字节码对象呢?
* 所有的数据类型(引用数据类型和基本数据类型)都有Class属性,即第一种获取Class对象的方法
*
* 九大内置Class实例:JVM中预先提供好的Class实例,有九种,byte short char int long double
* float boolean void(看Class的API)
*
* 在8大基本数据类型的包装类中都有一个常量:TYPE,用于返回该包装类对应的基本类的字节码对象
* system.out.println(Integer.class==int.class); //true
*
* 注意:Integer和int是不同的数据类型
* system.out.println(Integer.class==int.class); //false
*
*
* 数组的Class实例:数组是引用数据类型,数组其实是对象
* 如何来表示数组的Class实例
* 方式1:数组类型.class
* 方式2:数组对象.getclass
*
* 数组没有包名所以不能使用第三种方法,即 Class.forname(String className)
*
* 注意:所有的具有相同维数和相同元素类型的数组共享同一个字节码对象(非同一份字节码文件)
*
* Class: 描述所有的类型,所以Class类中应该具备所有类型
* object:描述所有的对象,所以在object类中应该具备所有对象的共同的方法
6.使用反射获取类中的方法
* 使用反射获取类中的方法
* 1).获取字节码对象
* 2).获取方法所在类的方法
* 3).获取方法
*
* Class类中的常用方法:
* public Method[] getMethods(): 获取包括自身和继承过来的所有public方法
* public Method[] getDeclaredMetheds(): 获取自身类中所有的方法(不包过继承的),和访问权限无关
*
* public Method getMethod(String methodName,Class>..paramentTypes):
* 表示调用指定的一个公共方法(包括继承的)
*
* 参数:
* methodName:表示被调用方法的名字
* paramentTypes:表示调用方法的参数的Class类型,如String.class
*
* public Method getDeclaredMethod(String methodName,Class>..paramentTypes):
* 表示调用指定的一个本类中的方法(不包括继承的)
*
* 参数:
* methodName:表示被调用方法的名字
* paramentTypes:表示调用方法的参数的Class类型,如String.class
7.使用反射调用类中的方法
* 使用反射调用问题:
* 1).获取方法所在类的字节码对象
* 2).获取方法对象
* 3).使用反射调用方法
*
* 如何使用反射调用一个方法:
* 在Method类中的方法:
* public Object invoke(Object obj,Object...args):表示调用当前Method所表示的方法
* 参数:
* obj:表示被调用方法底层所属对象
* Method m=clz.getMethod("start",String.class);
* args:表示调用方法是传递的实际参数
*
* 返回:
* 底层方法的返回结果
*
//调用静态方法,则 public Object invoke(null,Object...args),第一个参数毫无意义
//这个null可以是任意值,因为静态方法的调用和对象无关
*
// 调用私有方法:
// 在调用私有方法之前应该设置该方法为可访问的
* 又因为Method是AccessibleObject子类,所以Method中具备该方法
* 所有在这道程序题中有:
* m3.setAccessible(true);
8.使用反射调用参数是数组的方法
* 使用反射调用数组参数:
* 调用方法的时候把实际参数统统作为Object数组的元素即可
* Method对象.invoke(方法底层所属对象,new Object[]{实参})
9.加载资源文件的路径
10.反射其他的API