Java 反射,就是在运行状态中。
- 获取任意类的名称、package信息、所有属性、方法、注解、类型、类加载器等
- 获取任意对象的属性,并且能改变对象的属性
- 调用任意对象的方法
- 判断任意一个对象所属的类
- 实例化任意一个类的对象
Java 的动态就体现在这。通过反射我们可以实现动态装配,降低代码的耦合度;动态代理等。反射的过度使用会严重消耗系统资源。
JDK 中 java.lang.Class 类,就是为了实现反射提供的核心类之一。
下面列举一些反射的几个主要函数:
package try1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 反射的基础方法
*2019/11/13
**/
public class Try {
public static void main(String[] args) {
Example e1 = new Example();
// System.out.println(e1.getClassMethod1().getName());
// System.out.println(e1.getClassMethod2().getName());
// System.out.println(e1.getClassMethod3().getName());
e1.geMethods();
}
}
class Example{
/**
* 方式一.通过类的getClass()方法
* 都已经得到对象了,反射显得多余
**/
public Class getClassMethod1(){
ManDemo md = new ManDemo();
return md.getClass();
}
/**
* 方式二.通过类的.class 获取
* 强依赖,需要引入相关类
**/
public Class getClassMethod2(){
// ManDemo md = new ManDemo();
return ManDemo.class;
}
/**
* 方式三.通过 Class.forName("") 获取
* 灵活 首要选择
* 这里需要注意,通过类的全路径名获取Class对象会抛出一个异常,如果根据类路径找不到这个类那么就会抛出这个异常。
**/
public Class getClassMethod3(){
Class c = null;
try {
c = Class.forName("try1.ManDemo");
c.getName();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return c;
}
/**
* 类装载器 ClassLoader
* ClassLoader是一个重要的Java运行时系统组件,负责在运行时查找和装载Class字节码文件
* JVM运行时会产生3个:
* ClassLoader:根装载器 、 ExtClassLoader 扩展类装载器 、AppClassLoader应用类装载器
* 其中根装载器是C++中的方法 ,故在java中看不到它,无法获取句柄
* 根装载器负责装载JRE的核心类库,ExtClassLoader扩展类装载器 和 AppClassLoader应用类装载器都是ClassLoader的子类
* ExtClassLoader负责装载JRE扩展目录ext中的JAR类包;
* AppClassLoader负责装载Classpath路径下的类包
* 由于 全盘负责委托机制 的存在 故优先父级加载
*
**/
public Class getClassMethod4(){
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class c = null;
try{
c = loader.loadClass("try1.ManDemo");
}catch (Exception e){
e.printStackTrace();
}
return c;
}
/**
* 获取构造方法
* @Date 2019/11/14
**/
public void getConstructors(){
Class c = getClassMethod3();
//获取所有构造方法
System.out.println("----------获取所有public构造方法-----------");
Constructor[] constructors = c.getConstructors();
for (Constructor cc:constructors) {
System.out.println(cc);
}
System.out.println("----------获取所有声明过的构造方法-----------");
Constructor[] constructors2 = c.getDeclaredConstructors();
for (Constructor cc:constructors2) {
System.out.println(cc);
}
try {
System.out.println("----------获取共有单独构造方法-----------");
System.out.println( c.getConstructor(String.class,Integer.class));
System.out.println( c.getConstructor(Integer.class,String.class));
System.out.println( c.getConstructor());
System.out.println("----------获取单独所有声明过的构造方法-----------");
System.out.println( c.getDeclaredConstructor(String.class));
System.out.println( c.getDeclaredConstructor(Integer.class,String.class));
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
/**
* 获取类属性
* @Date 2019/11/14
**/
public void getFields(){
Class c = getClassMethod3();
System.out.println("----------获取所有共有字段------------");
Field[] fields = c.getFields();
for (Field f: fields) {
System.out.println(f);
}
System.out.println("----------获取所有声明过的字段------------");
Field[] fields1 = c.getDeclaredFields();
for (Field f: fields1) {
System.out.println(f);
}
System.out.println("----------获取共有字段并使用-----------");
try {
//获得指定的共有字段
Field field = c.getField("sex");
//获取一个公有构造方法,并实例化
Object obj = c.getConstructor().newInstance();
//为属性设置值
field.set(obj,true);
ManDemo man = (ManDemo)obj;
System.out.println(man.sex);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("----------获取私有字段并使用-----------");
try {
Field nameField = c.getDeclaredField("name");
Object obj2 = c.getConstructor().newInstance();
//设置暴力反射 允许修改私有字段 否则修改私有字段会产生异常
nameField.setAccessible(true);
nameField.set(obj2,"王舞");
ManDemo man = (ManDemo)obj2;
System.out.println(man.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取类中方法
* @Date 2019/11/14
**/
public void geMethods(){
Class c = getClassMethod3();
System.out.println("----------获取所有共有方法------------");
Method[] methods = c.getMethods();
for (Method m:methods) {
System.out.println(m);
}
Method[] methods1 = c.getDeclaredMethods();
System.out.println("----------获取所有方法------------");
for (Method m:methods1) {
System.out.println(m);
}
try {
Object obj = c.getConstructor().newInstance();
System.out.println("----------获取特定的方法并使用(不带参)------------");
Method m = c.getMethod("sleep");
m.invoke(obj);
System.out.println("----------获取特定的方法并使用(不带参、私有)------------");
Method m1 = c.getDeclaredMethod("think");
m1.setAccessible(true);
m1.invoke(obj);
System.out.println("----------获取特定的方法并使用(带参)------------");
Method m2 = c.getDeclaredMethod("eat1",String.class);
m2.invoke(obj,"杨梅");
c.getDeclaredMethod("drunk",String.class,Integer.class).invoke(obj,"橙汁",3);
} catch (Exception e) {
e.printStackTrace();
}
}
}