一、获取class对象的方式
1、通过类的class属性获取,该方法最为安全可靠,程序性能最高;
Class clazz = Person.class;
2、通过对象调用getclass()方法来获取
Class clazz2 = "abc".getClass();
3、通过class对象的forName()静态方法获取,但可能抛出ClassNotFoundException()异常。
Class clazz3 = Class.forName("java.lang.String");
示例代码:
Class clazz = Class.forName("com.hundsun.base.reflect.sys.Person");
//利用.newInstance()方法来创建类的一个实例对象,实际调用的是类的无参构造器;
//一般类若声明了一个有参构造器,也要声明一个无参构造器
Object object = clazz.newInstance();
System.out.println(object);
二、Class类的常用方法
三、
类加载器ClassLoader
类装载器是用来把类(class)装载进 JVM 的。JVM 规范定义了两种类型的类装载器:启动类装载器(bootstrap)和用户自定义装载器(user-defined class loader)。 JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,如下图所示:
示例代码:
//1、获取系统类加载器
ClassLoader loader = ClassLoader.getSystemClassLoader();
System.out.println(loader);
//2、获取系统类加载器的父类加载器
loader = loader.getParent();
System.out.println(loader);
//3、获取扩展类加载器的父类加载器
loader = loader.getParent();
System.out.println(loader);
//4、测试当前类由哪个类加载器进行加载
loader = Class.forName("com.hundsun.base.reflect.sys.Person").getClassLoader();
System.out.println(loader);
//5、测试JDK提供的 Object类由哪个类加载器加载
loader = Class.forName("java.lang.Object").getClassLoader();
System.out.println(loader);
//6、类加载器获取文件流
InputStream in = this.getClass().getClassLoader().getResourceAsStream("com/hundsun/Person");
System.out.println(in);
四、反射作用
1、在运行时构造任意一个对象;
2、在运行时获取任意一个类所具有的成员变量和方法;
3、在运行时调用任意一个对象的方法(属性);
4、生成动态代理
五、反射应用
1、在运行时构造一个类的对象:
•调用 Class 对象的 newInstance() 方法
•调用 Constructor 对象的 newInstance(Object... initargs)
2、Constructor 对象
•代表构造器对象
•获取 Constructor:
•相关方法:
–
newInstance(
Object... initargs)
–
setAccessible(boolean flag)
3、Method方法
•代表方法
•Class 对象获取 Method 的方法:
–
getMethods()
•Method 对象的方法:
注:
getMethods()方法不能获取private方法。
getDeclaredMethods()方法获取所有方法,且只获取当前类所
名,例如;Method setBrand = clazz.getMethod("setBrand", String.class);)。
invoke(
Object obj,
Object... args)
通过method对象执行方法(例如:setBrand.invoke(car, "奥迪");)。
4、Field
获取Field数组:Field[] field = clazz.getDeclaredFields();
获取指定名字的Field:Field fieldf = clazz.getDeclaredField("name");
如果需要获取私有的field,则需要setAccessible(true)。
5、动态代理
a、需要一个被代理的对象;
b、类加载器通常是和被代理对象使用相同的类加载器
c、一般,Proxy.newInstance()的返回值是一个被代理对象实现的接口的类型,也可以是其他的接口类型(
注意:第二个参数,必须是一个接口类型的数组。提示:如果代理对象不需要额外实现被代理对象实现的接口
以外的接口,可以使用target.getClass().getInterfaces());
d、InvocatationHandler 通常使用匿名内部类的方式;被代理对象需要是final类型;
e、InvocatationHandler 的invoke()方法中的第一个参数Object类型的proxy指的是正在被返回的那个代理对象,一般情况下不适用。