16---java反射机制04(深入如了解)

 

1、通过反射机调用类中的方法:
 在正常情况下一个类的对象功能产生后,就可以直接调用类中的方法了,如果想
 调用的话,则肯定必须清楚的知道要调用的方法的名字是什么,之后通过Class类中的
 方法,得到一个方法的Method 对象,之后通过Method对象
 来执行方法,但是在方法调用的时候,会牵扯到方法中的参数问题,所以通过getMethod()取得
 的时候,必须设置好需要的参数类型;
 执行调用的方法是:invoke方法,执行的时候需要传递参数进去,而且需要实例化对象;
   package com.lid;
   interface China{//定义China接口
     public static final String NATIONAL="China";//定以全局常量
     public static final String AUTHOR="lid";//定以全局常量
     public void sayChina();//无参数的,没有返回值得方法
     public String sayHello(String name,int age);//定义有两参数的方法
    }
   public class Demo implements China{
     private String name;
     private int age;
     public Demo(){}
     public Demo(String name){
       this.name=name;
      }
     public Demo(String name,int age){
       this(name);
       this.age=age;
     }
    public void setName(String name){
      this.name=name;
     }
    public void setAge(int age){
      this.age=age;
     }
    public String getName(){
      return this.name;
     }
    public int getAge(){
      return this.age;
     }
    public void sayChina(){//覆写方法
      System.out.println("作者:"+AUTHOR+",国籍"+NATIONAL);
     }
    public String sayHello(String name,int age){
      return name+",你好!我今年:"+age+"岁了";
     }
   }  

   package com.lid.demo02;
   import java.lang.reflect.*;
   public class InvokeSayChina{
    public static void main(String args[]){
      Class<?> c1=null;
      try{
        c1=Class.forName("com.lid.Demo");//实例化Class对象
        Method met=c1.getMethod("sayChina");//找到sayChina方法---通过方法名和参数类型
        met.invoke(c1.newInstance());//调用方法
       }
      catch(Exception e){
        e.printStackTrace();
       }
      
     }
    }
   同过反射调用无参数的方法的整体思路:
    (1).创建Demo的Class类对象【Class.forName("com.lid.Demo")】;
    (2).通过Class类对象的方法得到想要的方法【c1.getMethod("sayChina")】;
    (3).通过Method类型的对象执行找到的方法【met.invoke(c1.newInstance())】;
 
2、得到带参数的方法:
   package com.lid.demo02;
   import java.lang.reflect.*;
   public class InvokeSayHello{
    public static void main(String args[]){
      Class<?> c1=null;
      try{
        c1=Class.forName("com.lid.Demo");//实例化Class对象
        Method met=c1.getMethod("sayHello",String.class,int.class);//找到sayChina方法---通过方法名和参数类型
        String rv;
        rv=(String)met.invoke(c1.newInstance(),"lid",20);//调用方法
        System.out.println(rv);
       }
      catch(Exception e){
        e.printStackTrace();
       }
      
     }
    }

3、通过反射机制调用Setter和Getter方法:
 setter和getter方法是一个标准的属性的访问方法,如果一个类的属性被封装,必须通过setter和getter方法来设置和
 取得,实际上此方法的操作之所以这样规定:主要是因为反射机制给予支持的;

 通过反射机制调用setter和getter方法:
  如果想调用setter,例如属性:name属性,则这样设置setter方法--setName(),方法的第二个单词首字母大写;
    package com.lid.demo02;
    import java.lang.reflect.*;
    public class InvokeSayChina{
     public static void main(String args[]){
       Class<?> c1=null;
       Object obj=null;
       try{
         c1=Class.forName("com.lid.Demo");//实例化Class对象
         obj=c1.newInstance();
         setter(obj,"name","lid",String.class);
         setter(obj,"age",20,int.class);
         
         System.out.println("姓名:");
         getter(obj,"name");
         System.out.println("年龄:");
         getter(obj,"age");
        }
       catch(Exception e){
         e.printStackTrace();
        }
      }
      public static String initStr(String old){
        String str=old.substring(0,1).toUpperCase()+old.substring(1);
        return str;
       }
      /**
       Object obj:要操作的对象
       String att:要操作的属性
       Object value:要设置的属性内容
       Class<?> type: 要设置的属性类型
      */
      public static void setter(Object obj,String att,Object value,Class<?> type){
       try{
         Method met=obj.getClass().getMethod("set"+initStr(att),type);
         met.invoke(obj,value);//设置setter的内容
        }
       catch(Exception e){
        }   
       }
       
      public static void getter(Object obj,String att) throws Exception{
        
       try{
         Method met=obj.getClass().getMethod("get"+initStr(att));
         
         System.out.println(met.invoke(obj));
        }
       catch(Exception e){
        } 
      }
     }
   以上的操作,在日后的开发中用户也许不会涉及的代码的开发,但是原来必须掌握;

4、通过反射调用属性:
  在访问私有属性是必须让这个属性可见:
   package com.lid.demo02;
   import java.lang.reflect.*;
   public class InvokeSayChina{
    public static void main(String args[]) throws Exception{
      Class<?> c1=null;
      Object obj=null;
      c1=Class.forName("com.lid.Demo");//实例化Class对象
      obj=c1.newInstance();
      Field nameField=null;
      Field ageField=null;
      nameField=c1.getDeclaredField("name");
      ageField=c1.getDeclaredField("age");
      nameField.setAccessible(true);//设置属性的可见
      ageField.setAccessible(true);
      nameField.set(obj,"lid");
      ageField.set(obj,20);
      System.out.println("姓名:"+nameField.get(obj));
      System.out.println("年龄:"+ageField.get(obj));
     }
    }

5、反射机制不光只能用在类中,也可以应用在任意的引用数据类型上,当然,这就包含了数组,
 数组使用Array类完成;
 Class类中存在以下方法:getComponentType()
  package com.lid.demo02;
  import java.lang.reflect.*;
  public class ClassArray{
   public static void main(String args[]) throws Exception{
     int temp[]={1,2,3};//声明一个数组
     Class<?> c=temp.getClass().getComponentType();//取得数组的Class对象
     System.out.println("类型:"+c.getName());//取得数组类型
     System.out.println("长度:"+Array.getLength(temp));//取得长度
     System.out.println("第一个内容:"+Array.get(temp,0));
     Array.set(temp,0,6);
     System.out.println("第一个内容:"+Array.get(temp,0));
    }
   }

 使用Array类还可以修改数组的大小
 修改的过程实际上就是一个创建的过程,创建一个新的数组,所以还要
  把就得内容拷贝到新的数组中去;
   package com.lid.demo02;
   import java.lang.reflect.*;
   public class ClassArray{
    public static void main(String args[]) throws Exception{
      int temp[]={1,2,3};//声明一个数组
      int newTemp[]=(int[])arrayInc(temp,5);//重新开辟一个数组
      print(newTemp);
     }
    public static Object arrayInc(Object obj,int len){
     Class<?> c=obj.getClass();
     Class<?> arr=c.getComponentType();//得到数组的Class 对象
     Object newO=Array.newInstance(arr,len);//开辟新的
     int co=Array.getLength(obj);
     System.arraycopy(obj,0,newO,0,co);//拷贝数据
     return newO;
     }
    public static void print(Object obj){//数组输出
     Class<?> c=obj.getClass();
     if(!c.isArray()){//判断是否是数组
       return;
      }
     Class<?> arr=c.getComponentType();
     System.out.println(arr.getName()+"数组的长度是:"+Array.getLength(obj));
     for(int i=0;i<Array.getLength(obj);i++){
       System.out.print(Array.get(obj,i)+" ");//通过Array 输出
      }
     }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bzuld

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值