1.反射的概念:
在Java中运行的类,有这么一面镜子,可以反射该类的一些行为和属性,而这个反射就体现在java.lang.Class中;
通过Class对象,可以得到某个类的一些行为和属性,甚至我们通过反射可以操作这个对象的行为和属性;这就是反射机制;
2.反射类class对象:在运行期间,只有一个class对象产生,唯一对应一个类。无论new出多少个对象,class对象只有一个。
3.反射使用场景:仅能拿到类的描述,拿不到类,却需要操作类的属性或方法。好比要买苹果,却不能拿出一个苹果的样品给卖家看,只能描述苹果的名称,样子。
4.实例代码
package org.szxu.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import javax.lang.model.element.VariableElement;
public class ReflectionMyself {
//public Object initByDefaultConst(Object obj) throws Throwable {
public Object initByDefaultConst() throws Throwable {
String className = "org.szxu.reflection.Car";
System.out.println(System.getProperty("sun.boot.class.path"));
System.out.println(System.getProperty("java.ext.dirs"));
System.out.println(System.getProperty("java.class.path"));
/* 第一部分:获取类的class信息 */
//1.通过类名.class方式获取类元数据对象,前提是能够类可见(这里没必要使用反射,只需知道类有个class属性即可)
//Class clazz = Car.class;
//2.通过getClass()方式获取类元数据对象,任何数据类型(包括基本数据类型)都有一个静态的class属性
//Class<?> clazz = new Car().getClass();
//3.通过Class.forName获取类元数据对象
Class clazz = Class.forName(className);
//4.1.通过本类装载器获取类元数据对象
//ClassLoader classLoader00 = this.getClass().getClassLoader(); //局限:仅能在非static方法中使用
ClassLoader classLoader = ReflectionMyself.class.getClassLoader(); //方法所在类名.class
Class clazz_12 = classLoader.loadClass(className);
//4.2.通过类装载器获取类元数据对象
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class clazz_11 = loader.loadClass(className);
//System.out.println(clazz_11 == clazz_12);
//System.out.println(clazz_12 == clazz_2);
//System.out.println(clazz_2 == clazz);
/* 第二部分:获取类的实例 */
//1.1.获取类的默认构造器对象:公有构造器
//Constructor constructor_public = clazz.getConstructor(); //仅取到构造器为public,不能获取private修饰的构造器
//System.out.println(constructor_public.getName());
//1.2.获取类的默认构造器对象:私有构造器
Constructor constructor_private = clazz.getDeclaredConstructor(); //可获取private修饰的Constructor对象
System.out.println(constructor_private.getName());
//1.3.获取指定参数的公有构造器
Constructor constructor_params = clazz.getConstructor(String.class, String.class, int.class);
System.out.println(constructor_params.getName());
//1.4.获取指定参数的私有构造器
Constructor constructor_params_private = clazz.getDeclaredConstructor(String.class, String.class, int.class, int.class);
System.out.println(constructor_params.getName());
constructor_params_private.setAccessible(true);
//2.1.通过构造器实例化对象:公有构造器
//Object carObject = constructor_public.newInstance();
//2.2.通过构造器实例化对象:私有构造器,前提是调用一下setAccessible(true)获取调用私有方法的权限,否则会报异常
/*constructor_private.setAccessible(true);
Object carObject = constructor_private.newInstance();
System.out.println(carObject.toString());*/
//2.3.通过公有构造器实例化对象:带参数构造器
//Object carObject = constructor_params.newInstance("宝马", "白色", 200);
//2.4.通过私有构造器实例化对象:带参构造器
Object carObject = constructor_params_private.newInstance("宝马", "白色", 200, 2);
/* 第三部分:使用类的方法和属性 */
//1.1.直接设置字段值;直接获取字段值
Field brandField = clazz.getDeclaredField("brand"); //设置铭牌
brandField.setAccessible(true);
brandField.set(carObject, "别克300");
System.out.println("brand:" + (String)brandField.get(carObject));
Field colorField = clazz.getDeclaredField("color"); //设置颜色
colorField.setAccessible(true);
colorField.set(carObject, "别克白色");
System.out.println("brand:" + (String)colorField.get(carObject));
Field speedField = clazz.getDeclaredField("maxSpeed"); //设置最大速度
speedField.setAccessible(true);
speedField.set(carObject, 260);
System.out.println("brand:" + (int)speedField.get(carObject));
//1.2.通过属性方法设置私有字段
Method setBrand = clazz.getDeclaredMethod("setBrand", String.class); //设置铭牌
setBrand.invoke(carObject, "红旗CA72");
System.out.println(clazz.getMethod("getBrand").invoke(carObject));
Method setColor = clazz.getMethod("setColor", String.class); //设置颜色
setColor.invoke(carObject, "黑色");
System.out.println(clazz.getMethod("getColor").invoke(carObject));
Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class); //设置最大速度
setMaxSpeed.invoke(carObject, 200);
System.out.println(clazz.getMethod("getMaxSpeed").invoke(carObject));
//2.1.调用一般方法:public方法,公有方法也可以使用getDeclaredMethod来调用保证参数正确即可
Method introduceMethod_public = clazz.getDeclaredMethod("introduce");
introduceMethod_public.invoke(carObject, null);
//2.2.调用一般方法:private方法(参数严格匹配) + 方法返回值为object
//Method introduceMethod_private = clazz.getDeclaredMethod("introduce", null);
Method introduceMethod_private = clazz.getDeclaredMethod("introduce", String.class);
introduceMethod_private.setAccessible(true);
Object result = introduceMethod_private.invoke(carObject, "别克");
//2.3.调用一般方法:static方法,invoke的第一个参数是null,不能去掉这个参数
Method introduceMethod_static = clazz.getMethod("introduce", String.class, String.class, int.class);
introduceMethod_static.invoke(null, "别克", "白色", 200);
//2.3.1.打印方法签名
int a = introduceMethod_static.getModifiers(); //拿到修饰符代表的数字
String aString = Modifier.toString(a); //对数字进行解析,这里是public static
Class reTy = introduceMethod_static.getReturnType(); //返回类型,全称
Class[] paTy = introduceMethod_static.getParameterTypes(); //参数类型,全称的数组
StringBuilder strBuilder = new StringBuilder();
strBuilder.append(Modifier.toString(introduceMethod_static.getModifiers()) + " " +
introduceMethod_static.getReturnType().getSimpleName() + " " + introduceMethod_static.getName() + "(");
for (Class pC : paTy) {
String parameterTypeString = pC.getSimpleName();
strBuilder.append(parameterTypeString + ",");
}
if(strBuilder.toString() != "") {
strBuilder.delete(strBuilder.length() - 1, strBuilder.length());
}
strBuilder.append(")");
System.out.println(strBuilder);
//第四部分:获取所有方法参数和返回值
//构造方法
Constructor[] constructors = clazz.getDeclaredConstructors();
for(Constructor cons : constructors) {
StringBuilder strBuild = new StringBuilder();
strBuild.append(Modifier.toString(cons.getModifiers()) + " ");
strBuild.append(cons.getName() + "(");
String pTypeString = "";
for (Class pC : cons.getParameterTypes()) {
pTypeString = pC.getSimpleName();
strBuild.append(pTypeString + ",");
}
if(pTypeString != "") {
strBuild.delete(strBuild.length() - 1, strBuild.length());
}
strBuild.append(")");
System.out.println(strBuild);
}
//字段
Field[] fields = clazz.getDeclaredFields();
for(Field fied : fields) {
System.out.println(fied.getType().getSimpleName() + " " + fied.getName());
}
//成员方法
Method[] methods= clazz.getDeclaredMethods(); //获取类中所有方法,一定用getDeclaredMethods
for (Method method: methods) {
int aa = method.getModifiers(); //拿到修饰符代表的数字
String aaString = Modifier.toString(a); //对数字进行解析,这里是public static
Class reType = method.getReturnType(); //返回类型,全称
Class[] paType = method.getParameterTypes(); //参数类型,全称的数组
StringBuilder strBuild = new StringBuilder();
strBuild.append(Modifier.toString(method.getModifiers()) + " ");
strBuild.append(method.getReturnType().getSimpleName() + " ");
strBuild.append(method.getName() + "(");
for (Class pC : method.getParameterTypes()) {
String pTypeString = pC.getSimpleName();
strBuild.append(pTypeString + ",");
}
if(strBuild.toString() != "") {
strBuild.delete(strBuild.length() - 1, strBuild.length());
}
strBuild.append(")");
System.out.println(strBuild);
}
return carObject;
}
public static void main(String[] args) throws Throwable {
//Object car = new ReflectionMyself().initByDefaultConst(new Car());
Object car = new ReflectionMyself().initByDefaultConst();
}
}
参考文章:
1.https://www.jianshu.com/p/736e58d99bcf
2.待补充