爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      Java反射说得透彻一些

      首页 知识中心 软件开发 文章详情页

      Java反射说得透彻一些

      2024-04-23 07:20:43 阅读次数:45

      java,反射

      很多时候我们会遇到别人问一个问题:你给我讲一下反射,到底是什么东西?怎么实现的?我们能用反射来做什么?它有什么优缺点?下面我们会围绕着这几个问题展开: 

      一、反射机制是什么?

      反射是什么?什么是反?什么是正射? 有反就有正,我们知道正常情况, 如果我们希望创建一个对象,会使用以下的语句:

      Person person = new Person();
      

      其实我们第一次执行上面的语句的时候,JVM会先加载Person.class,加载到内存完之后,在方法区/堆中会创建了一个Class对象,对应这个Person类。这里有争议,有人说是在方法区,有些人说是在堆。个人感觉应该JVM规范说是在方法区,但是不是强制要求,而且不同版本的JVM实现也不一样。具体参考以下链接,这里不做解释: https:///xy-nb/p/6773051.html 而上面正常的初始化对象的方法,也可以说是“正射”,就是使用Class对象创建出一个Person对象。

      而反射则相反,是根据Person对象,获取到Class对象,然后可以获取到Person类的相关信息,进行初始化或者调用等一系列操作。

      在运行状态时,可以构造任何一个类的对象,获取到任意一个对象所属的类信息,以及这个类的成员变量或者方法,可以调用任意一个对象的属性或者方法。可以理解为具备了 动态加载对象 以及 对对象的基本信息进行剖析和使用 的能力。

      提供的功能包括:

      • 1.在运行时判断一个对象所属的类
      • 2.在运行时构造任意一个类的对象
      • 3.在运行时获取一个类定义的成员变量以及方法
      • 4.在运行时调用任意一个对象的方法
      • 5.生成动态代理

      灵活,强大,可以在运行时装配,无需在组件之间进行源代码链接,但是使用不当效率会有影响。所有类的对象都是Class的实例。 既然我们可以对类的全限定名,方法以及参数等进行配置,完成对象的初始化,那就是相当于增加了java的可配置性。

      这里特别需要明确的一点:类本身也是一个对象,方法也是一个对象,在Java里面万物皆可对象,除了基础数据类型...

      二、反射的具体使用

      2.1 获取对象的包名以及类名

      package invocation;
      public class MyInvocation {
          public static void main(String[] args) {
              getClassNameTest();
          }
          
          public static void getClassNameTest(){
              MyInvocation myInvocation = new MyInvocation();
              System.out.println("class: " + myInvocation.getClass());
              System.out.println("simpleName: " + myInvocation.getClass().getSimpleName());
              System.out.println("name: " + myInvocation.getClass().getName());
              System.out.println("package: " +
                      "" + myInvocation.getClass().getPackage());
          }
      }
      

      运行结果:

      class: class invocation.MyInvocation
      simpleName: MyInvocation
      name: invocation.MyInvocation
      package: package invocation
      

      由上面结果我们可以看到: 1.getClass():打印会带着class+全类名 2.getClass().getSimpleName():只会打印出类名 3.getName():会打印全类名 4.getClass().getPackage():打印出package+包名

      getClass()获取到的是一个对象,getPackage()也是。

      2.2 获取Class对象

      在java中,一切皆对象。java中可以分为两种对象,实例对象和Class对象。这里我们说的获取Class对象,其实就是第二种,Class对象代表的是每个类在运行时的类型信息,指和类相关的信息。比如有一个Student类,我们用Student student = new Student()new一个对象出来,这个时候Student这个类的信息其实就是存放在一个对象中,这个对象就是Class类的对象,而student这个实例对象也会和Class对象关联起来。 我们有三种方式可以获取一个类在运行时的Class对象,分别是

      • Class.forName("com.Student")
      • student.getClass()
      • Student.class

      实例代码如下:

      package invocation;
      
      public class MyInvocation {
          public static void main(String[] args) {
              getClassTest();
          }
          public static void getClassTest(){
              Class<?> invocation1 = null;
              Class<?> invocation2 = null;
              Class<?> invocation3 = null;
              try {
                  // 最常用的方法
                  invocation1 = Class.forName("invocation.MyInvocation");
              }catch (Exception ex){
                  ex.printStackTrace();
              }
              invocation2 = new MyInvocation().getClass();
              invocation3 = MyInvocation.class;
              System.out.println(invocation1);
              System.out.println(invocation2);
              System.out.println(invocation3);
          }
      }
      

      执行的结果如下,三个结果一样:

      class invocation.MyInvocation
      class invocation.MyInvocation
      class invocation.MyInvocation
      

      2.3 getInstance()获取指定类型的实例化对象

      首先我们有一个Student类,后面都会沿用这个类,将不再重复。

      class Student{
          private int age;
      
          private String name;
      
          public Student() {
          }
          public Student(int age) {
              this.age = age;
          }
      
          public Student(String name) {
               = name;
          }
          
          public Student(int age, String name) {
              this.age = age;
               = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
               = name;
          }
      
          @Override
          public String toString() {
              return "Student{" +
                      "age=" + age +
                      ", name='" + name + '\'' +
                      '}';
          }
      

      我们可以使用getInstance()方法构造出一个Student的对象:

          public static void getInstanceTest() {
              try {
                  Class<?> stduentInvocation = Class.forName("invocation.Student");
                  Student student = (Student) stduentInvocation.newInstance();
                  student.setAge(9);
                  student.setName("Hahs");
                  System.out.println(student);
      
              }catch (Exception ex){
                  ex.printStackTrace();
              }
          }
          
          
      输出结果如下:
      Student{age=9, name='Hahs'}
      

      但是如果我们取消不写Student的无参构造方法呢?就会出现下面的报错:

      java.lang.InstantiationException: invocation.Student
      	at java.lang.Class.newInstance(Class.java:427)
      	at invocation.MyInvocation.getInstanceTest(MyInvocation.java:40)
      	at invocation.MyInvocation.main(MyInvocation.java:8)
      Caused by: java.lang.NoSuchMethodException: invocation.Student.<init>()
      	at java.lang.Class.getConstructor0(Class.java:3082)
      	at java.lang.Class.newInstance(Class.java:412)
      	... 2 more
      

      这是因为我们重写了构造方法,而且是有参构造方法,如果不写构造方法,那么每个类都会默认有无参构造方法,重写了就不会有无参构造方法了,所以我们调用newInstance()的时候,会报没有这个方法的错误。值得注意的是,newInstance()是一个无参构造方法。

      2.4 通过构造函数对象实例化对象

      除了newInstance()方法之外,其实我们还可以通过构造函数对象获取实例化对象,怎么理解?这里只构造函数对象,而不是构造函数,也就是构造函数其实就是一个对象,我们先获取构造函数对象,当然也可以使用来实例化对象。

      可以先获取一个类的所有的构造方法,然后遍历输出:

          public static void testConstruct(){
              try {
                  Class<?> stduentInvocation = Class.forName("invocation.Student");
                  Constructor<?> cons[] = stduentInvocation.getConstructors();
                  for(int i=0;i<cons.length;i++){
                      System.out.println(cons[i]);
                  }
      
              }catch (Exception ex){
                  ex.printStackTrace();
              }
          }
      

      输出结果:

      public invocation.Student(int,java.lang.String)
      public invocation.Student(java.lang.String)
      public invocation.Student(int)
      public invocation.Student()
      

      取出一个构造函数我们可以获取到它的各种信息,包括参数,参数个数,类型等等:

          public static void constructGetInstance() {
              try {
                  Class<?> stduentInvocation = Class.forName("invocation.Student");
                  Constructor<?> cons[] = stduentInvocation.getConstructors();
                  Constructor constructors = cons[0];
                  System.out.println("name: " + constructors.getName());
                  System.out.println("modifier: " + constructors.getModifiers());
                  System.out.println("parameterCount: " + constructors.getParameterCount());
                  System.out.println("构造参数类型如下:");
                  for (int i = 0; i < constructors.getParameterTypes().length; i++) {
                      System.out.println(constructors.getParameterTypes()[i].getName());
                  }
              } catch (Exception ex) {
                  ex.printStackTrace();
              }
          }
      

      输出结果,modifier是权限修饰符,1表示为public,我们可以知道获取到的构造函数是两个参数的,第一个是int,第二个是String类型,看来获取出来的顺序并不一定是我们书写代码的顺序。

      name: invocation.Student
      modifier: 1
      parameterCount: 2
      构造参数类型如下:
      int
      java.lang.String
      

      既然我们可以获取到构造方法这个对象了,那么我们可不可以通过它去构造一个对象呢?答案肯定是可以!!! 下面我们用不同的构造函数来创建对象:

          public static void constructGetInstanceTest() {
              try {
                  Class<?> stduentInvocation = Class.forName("invocation.Student");
                  Constructor<?> cons[] = stduentInvocation.getConstructors();
                  // 一共定义了4个构造器
                  Student student1 = (Student) cons[0].newInstance(9,"Sam");
                  Student student2 = (Student) cons[1].newInstance("Sam");
                  Student student3 = (Student) cons[2].newInstance(9);
                  Student student4 = (Student) cons[3].newInstance();
                  System.out.println(student1);
                  System.out.println(student2);
                  System.out.println(student3);
                  System.out.println(student4);
      
              } catch (Exception ex) {
                  ex.printStackTrace();
              }
      

      输出如下:

      Student{age=9, name='Sam'}
      Student{age=0, name='Sam'}
      Student{age=9, name='null'}
      Student{age=0, name='null'}
      

      构造器的顺序我们是必须一一针对的,要不会报一下的参数不匹配的错误:

      java.lang.IllegalArgumentException: argument type mismatch
      	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
      	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
      	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
      	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
      	at invocation.MyInvocation.constructGetInstanceTest(MyInvocation.java:85)
      	at invocation.MyInvocation.main(MyInvocation.java:8)
      

      2.5 获取类继承的接口

      通过反射我们可以获取接口的方法,如果我们知道某个类实现了接口的方法,同样可以做到通过类名创建对象调用到接口的方法。

      首先我们定义两个接口,一个InSchool:

      public interface InSchool {
          public void attendClasses();
      }
      

      一个AtHome:

      public interface AtHome {
          public void doHomeWork();
      }
      

      创建一个实现两个接口的类Student.java

      public class Student implements AtHome, InSchool {
          public void doHomeWork() {
              System.out.println("I am a student,I am doing homework at home");
          }
      
          public void attendClasses() {
              System.out.println("I am a student,I am attend class in school");
          }
      }
      

      测试代码如下:

      public class Test {
          public static void main(String[] args) throws Exception {
              Class<?> studentClass = Class.forName("invocation.Student");
              Class<?>[] interfaces = studentClass.getInterfaces();
              for (Class c : interfaces) {
                  // 获取接口
                  System.out.println(c);
                  // 获取接口里面的方法
                  Method[] methods = c.getMethods();
                  // 遍历接口的方法
                  for (Method method : methods) {
                      // 通过反射创建对象
                      Student student = (Student) studentClass.newInstance();
                      // 通过反射调用方法
                      method.invoke(student, null);
                  }
              }
          }
      }
      

      结果如下: Java反射说得透彻一些

      可以看出其实我们可以获取到接口的数组,并且里面的顺序是我们继承的顺序,通过接口的Class对象,我们可以获取到接口的方法,然后通过方法反射调用实现类的方法,因为这是一个无参数的方法,所以只需要传null即可。

      2.6 获取父类相关信息

      主要是使用getSuperclass()方法获取父类,当然也可以获取父类的方法,执行父类的方法,首先创建一个Animal.java:

      public class Animal {
          public void doSomething(){
              System.out.println("animal do something");
          }
      }
      

      Dog.java继承于Animal.java:

      public class Dog extends Animal{
          public void doSomething(){
              System.out.println("Dog do something");
          }
      }
      

      我们可以通过反射创建Dog对象,获取其父类Animal以及创建对象,当然也可以获取Animal的默认父类Object:

      public class Test {
          public static void main(String[] args) throws Exception {
              Class<?> dogClass = Class.forName("invocation02.Dog");
              System.out.println(dogClass);
              invoke(dogClass);
      
              Class<?> animalClass = dogClass.getSuperclass();
              System.out.println(animalClass);
              invoke(animalClass);
      
              Class<?> objectClass = animalClass.getSuperclass();
              System.out.println(objectClass);
              invoke(objectClass);
          }
      
          public static void invoke(Class<?> myClass) throws Exception {
              Method[] methods = myClass.getMethods();
              // 遍历接口的方法
              for (Method method : methods) {
                  if (method.getName().equalsIgnoreCase("doSomething")) {
                      // 通过反射调用方法
                      method.invoke(myClass.newInstance(), null);
                  }
              }
          }
      }
      

      输入如下: Java反射说得透彻一些

      2.7 获取当前类的公有属性和私有属性以及更新

      创建一个Person.java,里面有静态变量,非静态变量,以及public,protected,private不同修饰的属性。

      public class Person {
      
          public static String type ;
      
          private static String subType ;
      
          // 名字(公开)
          public String name;
      
          protected String gender;
      
          private String address;
      
          @Override
          public String toString() {
              return "Person{" +
                      "name='" + name + '\'' +
                      ", address='" + address + '\'' +
                      '}';
          }
      }
      

      使用getFields()可以获取到public的属性,包括static属性,使用getDeclaredFields()可以获取所有声明的属性,不管是public,protected,private不同修饰的属性。

      修改public属性,只需要field.set(object,value)即可,但是private属性不能直接set,否则会报以下的错误。

      Exception in thread "main" java.lang.IllegalAccessException: Class invocation03.Tests can not access a member of class invocation03.Person with modifiers "private"
      	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
      	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
      	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
      	at java.lang.reflect.Field.set(Field.java:761)
      	at invocation03.Tests.main(Tests.java:21)
      

      那么需要怎么做呢?private默认是不允许外界操作其值的,这里我们可以使用field.setAccessible(true);,相当于打开了操作的权限。

      那static的属性修改和非static的一样,但是我们怎么获取呢? 如果是public修饰的,可以直接用类名获取到,如果是private修饰的,那么需要使用filed.get(object),这个方法其实对上面说的所有的属性都可以的。 测试代码如下

      public class Tests {
          public static void main(String[] args) throws Exception{
              Class<?> personClass = Class.forName("invocation03.Person");
              Field[] fields = personClass.getFields();
              // 获取公开的属性
              for(Field field:fields){
                  System.out.println(field);
              }
              System.out.println("=================");
              // 获取所有声明的属性
              Field[] declaredFields = personClass.getDeclaredFields();
              for(Field field:declaredFields){
                  System.out.println(field);
              }
              System.out.println("=================");
              Person person = (Person) personClass.newInstance();
               = "Sam";
              System.out.println(person);
      
              // 修改public属性
              Field fieldName = personClass.getDeclaredField("name");
              fieldName.set(person,"Jone");
      
              // 修改private属性
              Field addressName = personClass.getDeclaredField("address");
              // 需要修改权限
              addressName.setAccessible(true);
              addressName.set(person,"东风路47号");
              System.out.println(person);
      
              // 修改static 静态public属性
              Field typeName = personClass.getDeclaredField("type");
              typeName.set(person,"人类");
              System.out.println(Person.type);
      
              // 修改静态 private属性
              Field subType = personClass.getDeclaredField("subType");
              subType.setAccessible(true);
              subType.set(person,"黄种人");
              System.out.println(subType.get(person));
          }
      }
      

      结果: Java反射说得透彻一些

      从结果可以看出,不管是public,还是protected,private修饰的,我们都可以通过反射对其进行查询和修改,不管是静态变量还是非静态变量。 getDeclaredField()可以获取到所有声明的属性,而getFields()则只能获取到public的属性。对于非public的属性,我们需要修改其权限才能访问和修改:field.setAccessible(true)。

      获取属性值需要使用field.get(object),值得注意的是:每个属性,其本身就是对象

      2.8 获取以及调用类的公有/私有方法

      既然可以获取到公有属性和私有属性,那么我想,执行公有方法和私有方法应该都不是什么问题? Java反射说得透彻一些

      那下面我们一起来学习一下...

      先定义一个类,包含各种修饰符,以及是否包含参数,是否为静态方法,Person.java:

      public class Person {
          // 非静态公有无参数
          public void read(){
              System.out.println("reading...");
          }
      
          // 非静态公有无参数有返回
          public String getName(){
              return "Sam";
          }
      
          // 非静态公有带参数   
          public int readABookPercent(String name){
              System.out.println("read "+name);
              return 80;
          }
      
          // 私有有返回值
          private String getAddress(){
              return "东方路";
          }
      
          // 公有静态无参数无返回值
          public static void staticMethod(){
              System.out.println("static public method");
          }
      
          // 公有静态有参数
          public static void staticMethodWithArgs(String args){
              System.out.println("static public method:"+args);
          }
      
          // 私有静态方法
          private static void staticPrivateMethod(){
              System.out.println("static private method");
          }
      }
      

      首先我们来看看获取里面所有的方法:

      public class Tests {
          public static void main(String[] args) throws Exception {
              Class<?> personClass = Class.forName("invocation03.Person");
              Method[] methods = personClass.getMethods();
              for (Method method : methods) {
                  System.out.println(method);
              }
      
              System.out.println("=============================================");
              Method[] declaredMethods = personClass.getDeclaredMethods();
              for (Method method : declaredMethods) {
                  System.out.println(method);
              }
          }
      }
      

      结果如下: Java反射说得透彻一些 咦,我们发现getMethods()确实可以获取所有的公有的方法,但是有一个问题,就是他会把父类的也获取到,也就是上面图片绿色框里面的,我们知道所有的类默认都继承了Object类,所以它把Object的那些方法都获取到了。 而getDeclaredMethods确实可以获取到公有和私有的方法,不管是静态还是非静态,但是它是获取不到父类的方法的。

      那如果我们想调用方法呢?先试试调用非静态方法:

      public class Tests {
          public static void main(String[] args) throws Exception {
              Class<?> personClass = Class.forName("invocation03.Person");
              Person person = (Person) personClass.newInstance();
              Method[] declaredMethods = personClass.getDeclaredMethods();
              for (Method method : declaredMethods) {
                  if(method.getName().equalsIgnoreCase("read")){
                      method.invoke(person,null);
                      System.out.println("===================");
                  }else if(method.getName().equalsIgnoreCase("getName")){
                      System.out.println(method.invoke(person,null));
                      System.out.println("===================");
                  }else if(method.getName().equalsIgnoreCase("readABookPercent")){
                      System.out.println(method.invoke(person,"Sam"));
                      System.out.println("===================");
                  }
              }
      
          }
      }
      

      结果如下,可以看出method.invoke(person,null);是调用无参数的方法,而method.invoke(person,"Sam")则是调用有参数的方法,要是有更多参数,也只需要在里面多加一个参数即可,返回值也同样可以获取到。 Java反射说得透彻一些

      那么private方法呢?我们照着来试试,试试就试试,who 怕 who?

      public class Tests {
          public static void main(String[] args) throws Exception {
              Class<?> personClass = Class.forName("invocation03.Person");
              Person person = (Person) personClass.newInstance();
              Method[] declaredMethods = personClass.getDeclaredMethods();
              for (Method method : declaredMethods) {
                  if(method.getName().equalsIgnoreCase("getAddress")){
                      method.invoke(person,null);
                  }
              }
      
          }
      }
      

      结果报错了:

      Exception in thread "main" java.lang.IllegalAccessException: Class invocation03.Tests can not access a member of class invocation03.Person with modifiers "private"
      	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
      	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
      	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
      	at java.lang.reflect.Method.invoke(Method.java:491)
      	at invocation03.Tests.main(Tests.java:13)
      

      Java反射说得透彻一些

      一看就是没有权限,小场面,不要慌,我来操作一波,只要加上

      method.setAccessible(true);
      

      哦豁,完美解决了... Java反射说得透彻一些

      那么问题来了,上面说的都是非静态的,我就想要调用静态的方法。 当然用上面的方法,对象也可以直接调用到类的方法的: Java反射说得透彻一些

      一点问题都没有,为什么输出结果有几个null,那是因为这函数是无返回值的呀,笨蛋...

      如果我不想用遍历方法的方式,再去判断怎么办?能不能直接获取到我想要的方法啊?那答案肯定是可以啊。

      public class Tests {
          public static void main(String[] args) throws Exception {
              Class<?> personClass = Class.forName("invocation03.Person");
              Person person = (Person) personClass.newInstance();
              Method method = personClass.getMethod("readABookPercent", String.class);
              method.invoke(person, "唐诗三百首");
          }
      }
      

      结果和上面调用的完全一样,图我就不放了,就一行字。要是这个方法没有参数呢?那就给一个null就可以啦。或者不给也可以。

      public class Tests {
          public static void main(String[] args) throws Exception {
              Class<?> personClass = Class.forName("invocation03.Person");
              Person person = (Person) personClass.newInstance();
              Method method = personClass.getMethod("getName",null);
              System.out.println(method.invoke(person));
          }
      }
      

      三、反射的优缺点

      3.1 优点

      反射可以在不知道会运行哪一个类的情况下,获取到类的信息,创建对象以及操作对象。这其实很方便于拓展,所以反射会是框架设计的灵魂,因为框架在设计的时候,为了降低耦合度,肯定是需要考虑拓展等功能的,不能将类型写死,硬编码。

      降低耦合度,变得很灵活,在运行时去确定类型,绑定对象,体现了多态功能。

      3.2 缺点

      这么好用,没有缺点?怎么可能!!!有利就有弊,事物都是有双面性的。 即使功能很强大,但是反射是需要动态类型的,JVM没有办法优化这部分代码,执行效率相对直接初始化对象较低。一般业务代码不建议使用。

      反射可以修改权限,比如上面访问到private这些方法和属性,这是会破坏封装性的,有安全隐患,有时候,还会破坏单例的设计。

      反射会使代码变得复杂,不容易维护,毕竟代码还是要先写给人看的嘛,逃~

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.51cto.com/u_13604316/2674544,作者:秦怀杂货店,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:Java的wait()、notify()学习三部曲之一:JVM源码分析

      下一篇:【Java基础】-- instanceof 用法详解

      相关文章

      2025-05-14 10:02:58

      java休眠到指定时间怎么写

      java休眠到指定时间怎么写

      2025-05-14 10:02:58
      java , sleep , Thread , util , 方法
      2025-05-14 10:02:58

      java项目多端数据同步解决方案

      多端数据同步是指在多个设备(例如桌面应用、移动应用、Web应用)之间保持数据的一致性。

      2025-05-14 10:02:58
      java , Spring , WebSocket , 同步 , 数据 , 版本号
      2025-05-13 09:49:12

      Java学习(动态代理的思想详细分析与案例准备)(1)

      Java学习(动态代理的思想详细分析与案例准备)(1)

      2025-05-13 09:49:12
      java , 代理 , 代码 , 对象 , 接口 , 方法 , 需要
      2025-05-09 08:20:32

      基于IDEA的Maven简单工程创建及结构分析

      通过一个 mvn 命令直接让我们创建一个 Maven 的脚手架。

      2025-05-09 08:20:32
      java , Maven , xml , 创建 , 文件 , 文件夹 , 项目
      2025-05-08 09:03:57

      前K个高频元素java

      给定一个非空的整数数组,返回其中出现频率前 前K个高频元素java 高的元素。

      2025-05-08 09:03:57
      java , 元素 , 样例 , 给定
      2025-05-08 09:03:21

      基于java Swing开发的学生成绩管理系统【项目源码+数据库脚本】

      基于java Swing开发的学生成绩管理系统【项目源码+数据库脚本】

      2025-05-08 09:03:21
      java , Swing , 学生 , 源码
      2025-05-08 09:03:21

      java Swing学生成绩管理系统【项目源码+数据库脚本】

      本项目是一套基于java Swing开发的学生成绩管理系统,主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。

      2025-05-08 09:03:21
      java , 学生 , 成绩 , 数据库 , 源码
      2025-05-07 09:08:08

      java Swing学生选课管理系统【源码+数据库+报告】

      本项目是一套基于java Swing学生选课管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。

      2025-05-07 09:08:08
      java , 学生 , 截图 , 源码
      2025-05-07 09:08:08

      java swing人机对战五子棋(含背景音乐)

      本项目是一套基于java swing的人机对战五子棋系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。

      2025-05-07 09:08:08
      java , 源码
      2025-04-22 09:40:08

      【ETL工具】kettle 程序报错 Javascript error: TypeError: Cannot call method “trim“ of null

      【ETL工具】kettle 程序报错 Javascript error: TypeError: Cannot call method “trim“ of null

      2025-04-22 09:40:08
      java , javascript , org
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5241185

      查看更多

      最新文章

      java项目多端数据同步解决方案

      2025-05-14 10:02:58

      Java学习(动态代理的思想详细分析与案例准备)(1)

      2025-05-13 09:49:12

      前K个高频元素java

      2025-05-08 09:03:57

      基于java Swing开发的学生成绩管理系统【项目源码+数据库脚本】

      2025-05-08 09:03:21

      java Swing学生成绩管理系统【项目源码+数据库脚本】

      2025-05-08 09:03:21

      java Swing学生选课管理系统【源码+数据库+报告】

      2025-05-07 09:08:08

      查看更多

      热门文章

      JAVA__接口的作用

      2023-04-18 14:14:13

      Java学习之算术运算符两只老虎

      2023-04-19 09:23:13

      排序算法Java版-归并排序算法

      2023-04-24 11:25:19

      JAVA多线程学习笔记

      2023-05-11 06:05:48

      try...catch...finally java

      2023-03-29 09:40:26

      Java:apache.poi读写Excel文件

      2023-02-22 06:40:54

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      Java开发GUI之选择列表

      Java学习之算术运算符两只老虎

      从源码角度学习java函数式编程

      Java之入门程序及注释

      java alibaba fastjson自定义序列化反序列化(教你解决问题思路)

      Java中反射机制的使用与性能影响分析

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号