定义
存放于 java.lang.reflect 包中。new属于静态编译,反射属于动态编译,只有在运行时才会去获得该对象的实例。对于任意一个类都能知道并调用它所有的属性和方法。
优缺点
优点:降低类之间的耦合性,只需要给我一个路径就可以拿到我需要的东西,具体操作与你无关。
缺点:由于可以获取类中私有成员,破坏了类的封装使类变得不安全,还会降低程序性能。
第一步:获取类对象 Class
方法 | 说明 | 补充 |
类名.class | 基本数据类型的封装类可以通过 .TYPE 的方式获取其Class对象,但要注意TYPE实际上获取的是封装类对应的基本类型的Class对象的引用。因此 int.class==Integer.TYPE 返回true,int.class==Integer.class 返回 false。 | 需要导包,依赖性太强 |
Object.getClass () | 通过实例获取对应类对象。 | 都有对象了还反射个什么 |
Class.forName (类的完整路径) | 传入的路径是"包名.类名",需要处理可能抛出的 ClassNotFoundException 异常。 | 常用这种,传入的是字符串,可以做成配置文件 |
//类名获取
Class<Person> personClass = Person.class;
//对象获取
Person jinx = new Person("Jinx", 18);
Class<? extends Person> jinxClass = jinx.getClass();
//路径获取
Class<?> aClass = Class.forName("com.example.kotlinnotes.Person.java");
第二步:获取构造函数 Constructor
获取构造 | 说明 |
getDeclaredConstructors () | 获取全部的构造方法 |
getConstructors () | 只能获取全部的public构造方法 |
getDeclaredConstructor (Class<?>... parameterTypes) | 获取指定构造方法(传入的是 形参的类名.class) |
getConstructor (Class<?>... parameterTypes) | 只能获取指定的public构造方法(传入的是 形参的类名.class) |
//获取全部构造函数
Constructor<?>[] declaredConstructors = pathClass.getDeclaredConstructors();
//只获取全部的public构造函数
Constructor<?>[] constructors = pathClass.getConstructors();
//获取指定构造函数
Constructor<?> declaredConstructor = pathClass.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true); //如果是public构造就不用这步
Son sonPrivate = (Son) declaredConstructor.newInstance("sonPrivate", 18); //通过有参构造创建实例
//只获取指定的public构造函数
Constructor<?> constructor = pathClass.getConstructor();
Son sonPublic = (Son) constructor.newInstance(); //通过无参构造创建实例
第三步:创建实例对象 newInstance
创建对象 | 说明 |
Class 实例的 newInstance () | 只能通过无参构造创建对象 |
Constructors 实例的 newInstance () | 可以通过有参构造创建对象 |
//只能通过无参构造创建实例
Class<?> pathClass = Class.forName("com.example.kotlinnotes.knowledge.Son");
Son sonFromClass = (Son) pathClass.newInstance();
第四步:获取调用字段及方法 Field & Method
获取字段 (Class的方法) | 说明 |
getDeclaredFeilds () | 获取全部字段(不包括超类的) |
getFeilds () | 只能获取全部全部的public字段(包括超类的) |
getDeclaredFeild (String fieldName) | 获取指定字段 |
getFeild (String fieldName) | 只能获取指定的public字段 |
使用字段(Feild的方法) | 说明 |
get (Object obj) getByte (Object obj) getShort (Object obj) getInt (Object obj) getLong (Object obj) getDouble (Object obj) getFloat (Object obj) getChar (Object obj) getBoolean (Object obj) | 获取成员变量的值 (如果是基本类型的话有对应方法,避免类型转换的开销) |
set (Object obj) setByte (Object obj) setShort (Object obj) setInt (Object obj) setLong (Object obj) setDouble (Object obj) setFloat (Object obj) setChar (Object obj) setBoolean (Object obj) | 设置成员变量的值 (如果是基本数据类型的话有对应方法,避免类型转换的开销) |
getType () getGenericType () | 获取字段声明的数据类型,返回的是Class对象 如果字段声明的数据类型带泛型(参数化类型)则会带上泛型的数据类型,返回的是Type对象,否则打印出来的和上面一样 |
方法(ParameterizedType的方法) | 说明 |
getRawType () | 获取数据类型 |
getActualTypeArguments() | 获取泛型的数据类型 |
Class<?> pathClass = Class.forName("com.example.kotlinnotes.knowledge.Son");
Son sonFromClass = (Son) pathClass.newInstance();
//获取全部字段
Field[] declaredFields = pathClass.getDeclaredFields();
//只获取全部的public字段
Field[] fields = pathClass.getFields();
//获取指定字段
Field sonAgePrivate = pathClass.getDeclaredField("sonAgePrivate");
sonAgePrivate.setAccessible(true); //如果是pubnlic字段就不用这个
sonAgePrivate.getInt(sonFromClass); //0
sonAgePrivate.setInt(sonFromClass,100);
sonAgePrivate.getInt(sonFromClass); //100
//只获取指定的public字段
Field sonIsMalePublic = pathClass.getField("sonIsMalePublic");
sonIsMalePublic.getBoolean(sonFromClass); //false
sonIsMalePublic.setBoolean(sonFromClass,true);
sonIsMalePublic.getBoolean(sonFromClass); //true
Class<?> pathClass = Class.forName("com.example.kotlinnotes.knowledge.Son");
//基本类型的字段
Field sonIsMalePublic = pathClass.getField("sonIsMalePublic");
Class<?> typeBasic = sonIsMalePublic.getType();
System.out.println(typeBasic); //boolean
Type genericType1 = sonIsMalePublic.getGenericType();
System.out.println(genericType1); //boolean
System.out.println(genericType1.getTypeName()); //boolean
//自定义类型的字段
Field father = pathClass.getField("father");
Class<?> typeCustomize = father.getType();
System.out.println(typeCustomize); //class com.example.kotlinnotes.knowledge.Father
Type genericType2 = father.getGenericType();
System.out.println(genericType2); //class com.example.kotlinnotes.knowledge.Father
System.out.println(genericType2.getTypeName()); //com.example.kotlinnotes.knowledge.Father
//【List】参数化类型(带泛型的数据类型)
Field list = pathClass.getField("list");
Class<?> listType = list.getType();
System.out.println(listType); //class java.util.ArrayList
Type genericType3 = list.getGenericType();
System.out.println(genericType3); //java.util.ArrayList<java.lang.Integer>
System.out.println(genericType3.getTypeName()); //java.util.ArrayList<java.lang.Integer>
//【Map】参数化类型(带泛型的数据类型)
Field map = pathClass.getField("map");
Class<?> mapType = map.getType();
System.out.println(mapType); //interface java.util.Map
Type genericType4 = map.getGenericType();
System.out.println(genericType4); //java.util.Map<java.lang.String, java.lang.Integer>
if(genericType4 instanceof ParameterizedType){
//强制类型转换
ParameterizedType type = (ParameterizedType) genericType4;
//获取数据类型
Type rawType = type.getRawType();
System.out.println(rawType); //interface java.util.Map
//获取泛型的数据类型
Type[] actualTypeArguments = type.getActualTypeArguments();
Arrays.stream(actualTypeArguments).forEach(System.out::println); //class java.lang.String class java.lang.Integer
}else{
System.out.println("获取出错!");
}
获取方法(Class的方法) | 说明 |
getDeclaredMethods () | 获取全部方法(不包括继承的,仅本类/接口中的) |
getMethods () | 只能获取全部的public方法(包括继承来的:本类/接口中的+父类/接口中的+Object中的) |
getDeclaredMethod (String methodName, Class<?>... parameterTypes) | 获取指定方法(传入的是 方法名+形参的类名.class) |
getMethod (String methodName, Class<?>... parameterTypes) | 只能获取指定的public方法(传入的是 方法名+形参的类名.class) |
使用方法(Method的方法) | 说明 |
invoke (Object obj, Object... args) | 调用方法(参数一是调用该方法的实例对象,后面传方法的参数) |
setAccessible (boolean flag) | 如果调用的方法非public,则需要将Method对象设置为true |
Class<?> pathClass = Class.forName("com.example.kotlinnotes.knowledge.Son");
Son sonFromClass = (Son) pathClass.newInstance();
//获取全部方法
Method[] declaredMethods = pathClass.getDeclaredMethods();
//只能获取全部的public方法(包括继承)
Method[] methods = pathClass.getMethods();
//获取指定方法
Method sonMethodPrivate = pathClass.getDeclaredMethod("sonMethodPrivate", String.class, int.class);
sonMethodPrivate.setAccessible(true); //如果是public方法就不用这个
sonMethodPrivate.invoke(son,"调用指定的方法",2);
//只能获取指定的public方法
Method sonMethodPublic = pathClass.getMethod("sonMethodPublic", String.class, int.class);
sonMethodPublic.invoke(son,"调用指定的public方法",1);
其他方法
方法(Class的方法) | 说明 |
isPrimitive () isArray () isAnnotation () isInterface () isEnum () isAnonymousClass () | 基础类型? 接口? 枚举类? 匿名内部类? |
getName () getSimpleName () getPackage () getModifiers () getDeclaredClasses () getDeclaringClass () | 获取完整类名(含包名路径) 获取类名 获取包信息 获取类的访问权限 获取内部类 获取外部类 |
附:Son.class代码、Father.class 代码
public class Father {
private int fatherAgePrivate;
private String fatherNamePrivate;
public boolean fatherIsMalePublic;
public Father() {
this.fatherNamePrivate = "Default";
this.fatherAgePrivate = 0;
this.fatherIsMalePublic = false;
}
private Father(String fatherNamePrivate, int fatherAgePrivate) {
this.fatherNamePrivate = fatherNamePrivate;
this.fatherAgePrivate = fatherAgePrivate;
this.fatherIsMalePublic = false;
}
public Father(String fatherNamePrivate, int fatherAgePrivate, boolean fatherIsMalePublic) {
this.fatherNamePrivate = fatherNamePrivate;
this.fatherAgePrivate = fatherAgePrivate;
this.fatherIsMalePublic = fatherIsMalePublic;
}
public void fatherMethodPublic(String str, int num){
System.out.println("fatherMethodPublic:" + str + num);
}
private void fatherMethodPrivate(String str, int num){
System.out.println("fatherMethodPrivate:" + str + num);
}
}
public class Son extends Father {
private String sonNamePrivate;
private int sonAgePrivate;
public boolean sonIsMalePublic;
public Father father;
public ArrayList<Integer> list;
public Map<String,Integer> map;
public Son() {
this.sonNamePrivate = "Default";
this.sonAgePrivate = 0;
this.sonIsMalePublic = false;
}
private Son(String sonNamePrivate, int sonAgePrivate) {
this.sonNamePrivate = sonNamePrivate;
this.sonAgePrivate = sonAgePrivate;
this.sonIsMalePublic = false;
}
public Son(String sonNamePrivate, int sonAgePrivate, boolean sonIsMalePublic) {
this.sonNamePrivate = sonNamePrivate;
this.sonAgePrivate = sonAgePrivate;
this.sonIsMalePublic = sonIsMalePublic;
}
public void sonMethodPublic(String str, int num) {
System.out.println("sonMethodPublic:" + str + num);
}
private void sonMethodPrivate(String str, int num) {
System.out.println("sonMethodPrivate:" + str + num);
}
}