疫情期间,无法复工。正好趁这段时间,整理下开发这一路来的用到的,学到的知识点。希望疫情早点结束!
在实际Java开发中,反射应该不是一个很常用的技术,但他却是各个框架都需要用到的技术。
反射中最重要的有Class、 Constructor、Method、Field四个类。接下来就按照这个顺序进行描述。
先把需要的对象贴上来
Person对象
package com.chgo.javastrengthen.Reflect;
public class Person {
private String secret;
public String sex;
public void drink(){
System.out.println("每个人都需要喝水");
}
}
Student对象
package com.chgo.javastrengthen.Reflect;
public class Student extends Person{
public String name;
public int age;
public String school;
private int score;
public Student(){};
public Student(String name, int age, String school, int score) {
this.name = name;
this.age = age;
this.school = school;
this.score = score;
}
public Student(String name){
this.name = name;
}
public void setName(String name){
this.name = name;
}
private Student(int score){
this.score = score;
};
public int getScore(){
return score;
}
public static void doHomeWork(){
System.out.println("不写作业的学生不是好学生!");
}
private void dailyNote(){
System.out.println(name+"喜欢写日记!");
}
}
一、Class
运用反射技术,首先需要获取到反射对象。
获取反射对象的方法由如下四种:
1.1、
//类名.class Class clazz0 = Student.class;
1.2、
//class.forName(全路径名)
Class clazz1 = Class.forName("com.chgo.javastrengthen.Reflect.Student");
1.3、
//对象.getClass() Student student = new Student(); Class clazz2 = student.getClass();
1.4、
//使用类加载器获得
ClassLoader classLoader = Person.class.getClassLoader();
Class clazz3 = classLoader.loadClass("com.chgo.javastrengthen.Reflect.Student");

注意:使用类加载器去获得class对象,这个类加载器跟需要获得的类必须是同一级别。
二、Constructor
测试代码
public static void constructorOpe() throws Exception{
Class clazz = Student.class;
Constructor[] constructor = clazz.getDeclaredConstructors();
System.out.println("student 共有构造器"+constructor.length + "个");
Constructor[] constructorPub = clazz.getConstructors();
System.out.println("student 公开的构造器"+constructorPub.length + "个");
for (int i=0;i<constructor.length;i++) {
System.out.println("第"+i+"个构造器有"+constructor[i].getParameterCount()+"个构造参数,构造器修饰符为" + constructor[i].getModifiers());
Class[] paramTypes = constructor[i].getParameterTypes();
if (paramTypes.length==0){
System.out.println("无参构造方法");
}else {
System.out.print("构造参数分别为:");
for (Class type:paramTypes) {
System.out.println(type+"");
}
System.out.println();
}
}
Constructor constructor1 = clazz.getDeclaredConstructor(int.class);
constructor1.setAccessible(true);
Student xiaopang = (Student) constructor1.newInstance(11);
System.out.println("小胖的成绩是:"+xiaopang.getScore());
Constructor constructor2 = clazz.getConstructor(String.class);
constructor2.setAccessible(true);
Student daxiong = (Student) constructor2.newInstance("大熊");
System.out.println("新同学的名字:"+daxiong.name);
}

2.1、获取全部构造方法
Constructor[] constructor = clazz.getDeclaredConstructors();
2.2、获取修饰符为public的构造方法
Constructor[] constructorPub = clazz.getConstructors();
2.3、获取已知构造参数的私有的构造方法
Constructor constructor1 = clazz.getDeclaredConstructor(int.class);
2.4、获取已知构造参数的公开的构造方法
Constructor constructor2 = clazz.getConstructor(String.class);
2.5、获取constrctor对象的修饰符。
constructor.getModifiers()
2.6、获取constructor对象的构造参数个数
constructor.getParameterCount()
2.7、获取constructor对象的构造参数类型
Class[] paramTypes = constructor.getParameterTypes();
2.8、构造方法的强制访问
constructor1.setAccessible(true);
当构造方法是private类型的时候,方法调用会报IllegalAccessException异常。这时候就需要设置方法的可进入为true。强制访问
三、Field
3.1、获取本类中所有的参数(包括公开的和私有的)
Field[] fields = clazz.getDeclaredFields();
3.2、获取本类及父类中所有的修饰符为公开的参数
Field[] fieldspub = clazz.getFields();
3.3、获取field对象的修饰符
int i = fieldspub[i].getModifiers();
3.4、获取本类中已知参数名的field对象(包括私有的)
Field fieldscore = clazz.getDeclaredField("score");
3.5、获取本类及父类中已知参数名的修饰符为public的field对象
Field fieldsex=clazz.getField("sex");
3.6、通过field对象对主对象赋值
fieldscore.set(xiaoming,98);
两个参数,前面是需要赋值给到的对象,后面是需要赋的具体值。
如果field对象是private修饰的,一定需要用setAccessible(true)来进行强制访问。
测试代码及结果:
public static void fieldOpe() throws Exception {
Class clazz = Student.class;
Field[] fields = clazz.getDeclaredFields();
System.out.println("student 共有参数"+fields.length + "个");
for (int i=0;i<fields.length;i++){
System.out.println("第"+i+"参数为:" + fields[i].getName()+"修饰符为:"+fields[i].getModifiers());
}
Field[] fieldspub = clazz.getFields();
System.out.println("student及其父类person 有公开参数"+fieldspub.length + "个");
for (int i=0;i<fieldspub.length;i++){
System.out.println("第"+i+"参数为:" + fieldspub[i].getName()+"修饰符为:"+fieldspub[i].getModifiers());
}
Student xiaoming = new Student("小明");
Field fieldscore = clazz.getDeclaredField("score");
fieldscore.setAccessible(true);
fieldscore.set(xiaoming,98);
Field fieldsex=clazz.getField("sex");
fieldsex.set(xiaoming,"男生");
System.out.println(xiaoming.sex+xiaoming.name + "考试考了"+xiaoming.getScore());
}

四、Method
4.1、获取类中定义的所有方法,包括公开和私有的
Method[] methods = clazz.getDeclaredMethods();
4.2、获取类及父类中所有的修饰符为public的方法
Method[] methodspub = clazz.getMethods();
4.3、获取方法的修饰符
int i = methodspub[i].getModifiers()
4.4、获取方法中参数个数
int count = method.getParameterCount();
4.5、获取方法中需要的参数类型
Class[] types = methods[i].getParameterTypes();
4.6、获取方法中需要抛出的异常
Class[] exceptions = methods[i].getExceptionTypes();
4.7、获取本类中已知方法名和参数的method对象
Method method = clazz.getDeclaredMethod("dailyNote",String.class);
4.8、获取本类及父类中已知方法名和参数的修饰符为public的method对象
Method methodDrink = clazz.getMethod("drink");
4.9、使用已知主对象调用method方法
methodDrink.invoke(xiaohua,null);
4.10、如果方法是private修饰,需要设置权限为true
method.setAccessible(true);
注意:invoke参数为空的对象,第二个参数建议使用null
invoke 静态方法的时候,参数直接填null
测试代码及结果
public static void methodOpe() throws Exception {
Class clazz = Student.class;
Method[] methods = clazz.getDeclaredMethods();
System.out.println("student 共有方法"+methods.length + "个");
for (int i=0;i<methods.length;i++){
System.out.println("第"+i+"方法为:" + methods[i].getName()+"修饰符为:"+methods[i].getModifiers());
int count = methods[i].getParameterCount();
Class[] types = methods[i].getParameterTypes();
Class[] exceptions = methods[i].getExceptionTypes();
System.out.println("参数个数为:" +count);
if (types.length!=0){
for (Class type:types) {
System.out.println("参数分别为:" + type);
}
}
if (exceptions.length!=0){
System.out.println("抛出异常有"+exceptions.length);
for (Class exc:exceptions) {
System.out.println("参数分别为:" + exc);
}
}
}
Method[] methodspub = clazz.getMethods();
System.out.println("student 共有方法"+methodspub.length + "个");
Student xiaohua = new Student("小华");
Method method = clazz.getDeclaredMethod("dailyNote",String.class);
method.setAccessible(true);
method.invoke(xiaohua,"今天没发生啥");
Method methodDrink = clazz.getMethod("drink");
methodDrink.invoke(xiaohua,null);
}
以上就是Java反射中常用的方法及注意点。
本文主要介绍了Java反射的重要类Class、Constructor、Method、Field的使用,包括获取构造方法、字段和方法的各种方式,以及如何进行强制访问和方法调用。文中通过实例代码详细展示了反射的应用,并强调了在使用反射时的一些注意事项。
245

被折叠的 条评论
为什么被折叠?



