1.获取Class对象的方式
1.源文件阶段(引入了一个.class文件但是没有加载过)
//1.源文件阶段要获取Class对象
Class aClass = Class.forName("java_20211216.User");
2.Class对象阶段(.class文件通过类加载器加载过了)
//2.Class对象阶段获取Class对象
Class<User> userClass = User.class;
3.在对象运行阶段获取Class对象
//3.在对象运行阶段获取Class对象
User u1 = new User();
Class<? extends User> aClass1 = u1.getClass();
2.Class对象API
(1)获取字段对象
获取所有字段的方法:
1.得到类的所有public字段
Field[] getFields()
2. 返回类中所有的字段,包括:私、保、默、公
Field[] getDeclaredFields()
获取指定字段的方法:
1.获取某个"公有的"字段:
public Field getField(String fieldName);
2.获取某个字段(可以是私有的)
public Field getDeclaredField(String fieldName)
++ Field对象API
(1)获取字段的数据类型和修饰符
Field age = aClass1.getDeclaredField("age");
Class type = age.getType();//放回字段类型的Class对象
Type genericType = age.getGenericType();//对象从新封装成一个描述对象
String typeName = genericType.getTypeName();//=》java.lang.String
/**
* 如果只有一个修饰符返回单个修饰符的int值
* 如果多个则返回相加的值
*/
int modifiers = age.getModifiers();
//0:default 1:public 2:private 4:protected 8:static 16:final
(2)得到对象的属性值:get方法
User u1 = new User();
u1.name = "123";
User u2 = new User();
u2.name = "456";
Class<? extends User> aClass1 = u1.getClass();
Field name = aClass1.getDeclaredField("name");
String o = (String)name.get(u2);
System.out.println(o);
(3)给对象的属性赋值:set方法(对象的引用,要赋值的数值,不能给static修饰的类变量赋值)
User u1 = new User();
u1.name = "123";
User u2 = new User();
u2.name = "456";
Class<? extends User> aClass1 = u1.getClass();
Field age = aClass1.getDeclaredField("age");
age.setAccessible(true);//不管访问权限,或者是否是常量都能修改值
//如果给私有变量或者访问权限不够的变量以及final变量赋值不设置此选项就会抛出java.lang.IllegalArgumentException异常
age.set(u2,123);
System.out.println(u2.getAge());
(4)常见问题:
set(Object obj, Object value) 时,新value和原value的类型不一致导致,如下:无法转换类型导致的 java.lang.IllegalArgumentException(注意:反射获取或者修改一个变量的值时,编译器不会进行自动装/拆箱,所以int 和Integer需手动修改)
set(Object obj, Object value) 时,修改 final类型的变量导致的 IllegalAccessException。由于 Field 继承自 AccessibleObject , 我们可以使用 AccessibleObject.setAccessible() 方法告诉安全机制,这个变量可以访问即可解决,如field.setAccessible(true)。
getField(String name) 或getFields() 获取非 public 的变量,编译器会报 java.lang.NoSuchFieldException 错。
(2)获取构造器对象
//1.获取所有public修饰的构造器
Constructor[] constructors = userClass.getConstructors();
//2.获取所有构造器(私有、公共、默认)
Constructor[] declaredConstructors = userClass.getDeclaredConstructors();
//3.获取某个公共构造器(通过参数列表类型判断)
Constructor constructor = userClass.getConstructor(String.class);
//4.获取某个(私有、公共、默认)构造器(通过参数列表类型判断)
Constructor constructor2 = userClass.getDeclaredConstructor(String.class);
++Constructor 对象API
(1)获取构造器对象所在的类的Class对象
Constructor constructor2 = userClass.getDeclaredConstructor(String.class);
Class declaringClass = constructor2.getDeclaringClass();
(2)获取构造器的修饰符
int getModifiers()
//0:default 1:public 2:private 4:protected
(3)以字符串形式返回Constructor对象所表示得构造方法的名称。
String getName()
(4)返回由Constructor对象所表示的构造方法的形参类型对应Class对象组成的数组此
Class[] parameterTypes = constructor2.getParameterTypes();
System.out.println(Arrays.toString(parameterTypes));
(5)调用构造器对象创建对象方法 (newInstance)
Class<Math> mathClass = Math.class;
Constructor<Math> constructor = mathClass.getDeclaredConstructor();
constructor.setAccessible(true);
Math math = constructor.newInstance();
System.out.println(math);
(3)获取成员方法对象
1.批量的:
public Method[] getMethods(): 获取所有"公有方法";(包含了父类的方法也包含Object类)
public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
2.获取单个的:
public Method getMethod(String name,Class<?>... parameterTypes):
参数:
name : 方法名;
Class ... : 形参的Class类型对象
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
Method aa = userClass.getDeclaredMethod("aa", String.class, int.class);
++Method对象常用API
(1)调用方法invoke(无返回值情况)
Class userClass = User.class;
Method aa = userClass.getDeclaredMethod("aa", String.class, int.class);
aa.setAccessible(true);
User u1 = new User();
aa.invoke(u1, "高靖博", 12);
(2)调用方法invoke(有返回值情况)
Object cc = aa.invoke(u1, "高靖博", 12);
System.out.println(cc);
(3)获取方法的修饰符、返回值类型、参数列表、抛出异常类型
Class userClass = User.class;
Method cc = userClass.getDeclaredMethod("aa",String.class,int.class);
int modifiers = cc.getModifiers();//方法的修饰符:
//0:default 1:public 2:private 4:protected 8:static 16:final 1024:abstract 32:synchronized
Class [] parameterTypes = cc.getParameterTypes();//获取方法的参数列表Class对象
Class returnType = cc.getReturnType();//获取方法的放回值类型Class对象
Class [] exceptionTypes = cc.getExceptionTypes();//获取方法抛出的异常Class对象
String name = cc.getName();//获取的只有方法的名称
String s = cc.toGenericString();
System.out.println(s);
获取方法名:
String getName()
以 String 形式返回此 Method 对象表示的方法名称。
把方法转成字符串
String toGenericString()
返回描述此 Method 的字符串,包括类型参数。
(4)得到方法描述的Type类型方法
Type[] getGenericParameterTypes()
按照声明顺序返回 Type 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型的。
Type[] getGenericExceptionTypes()
返回 Type 对象数组,这些对象描述了声明由此 Method 对象抛出的异常。
Type getGenericReturnType()
返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象。
(5)判断的方法
判断方法:
boolean isBridge()
如果此方法是 bridge 方法,则返回 true;否则,返回 false。
boolean isSynthetic()
如果此方法为复合方法,则返回 true;否则,返回 false。
boolean isVarArgs()
如果将此方法声明为带有可变数量的参数,则返回 true;否则,返回 false。