Java巩固之路-----反射

本文主要介绍了Java反射的重要类Class、Constructor、Method、Field的使用,包括获取构造方法、字段和方法的各种方式,以及如何进行强制访问和方法调用。文中通过实例代码详细展示了反射的应用,并强调了在使用反射时的一些注意事项。

疫情期间,无法复工。正好趁这段时间,整理下开发这一路来的用到的,学到的知识点。希望疫情早点结束!

在实际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反射中常用的方法及注意点。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值