Java中的反射机制

一、概念

     反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。即把.class文件解刨分析(用于框架的设计)。

 

二、获取内容

1、基本文件

package com.shen2;
​
public class Person {

    public String name;  //字段或成员变量
    private int age;
    public final String password = "123";  //字段或成员变量


    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }

​
    public Person(){
        //System.out.println("person!!!!!");
    }

    public Person(String name){
        System.out.println(name);
    }


    private Person(int name){
        System.out.println(name);
    }

    public void eat(){
        System.out.println("eat!!!!");
    }

    public void run(String address){
        System.out.println("跑到" + address);
    }

    public void run(String address,int num[],String ss[]){
        System.out.println("跑到" + address + "," + num);
    }

    public String test(String str){

        return str + "aaaa";
    }

    private String test2(String str){

        return str + "aaaa";
    }

    public static String test3(String str){

        return str + "aaaa";
    }

    public static void main(String[] args) {
        System.out.println(args[0]);
    }
}

注意:一个类的属性有多少看get和set方法而不是字段

2、获取类

        // 方法1.该方法最长见
        Class clazz1 = Class.forName("com.shen2.Person");
​
        // 方法2
        //Class clazz2 = Person.class;
​
        // 方法3
        // Class clazz3 = new Person().getClass();
​
        //实例化
        Person p = (Person) clazz1.newInstance();

3、获取构造函数

    /**
     * 利用Constructor创建对象
     * 
     * @throws Exception
     */
​
    // 反射类无参的构造方法
    @Test
    public void test1() throws ClassNotFoundException, NoSuchMethodException,
            InstantiationException, IllegalAccessException,
            InvocationTargetException {
​
        Class clazz = Class.forName("com.shen2.Person");
​
        Constructor c = clazz.getConstructor(null);//null表示无参构造函数
​
        Object obj = c.newInstance(null);//创建实例
​
        System.out.println(obj);
    }
​
    // 反射类有参的构造方法:public Person(String name)
    @Test
    public void test2() throws ClassNotFoundException, NoSuchMethodException,
            InstantiationException, IllegalAccessException,
            InvocationTargetException {
​
        Class clazz = Class.forName("com.shen.Person");
​
        Constructor c = clazz.getConstructor(String.class);//string.class表示参数类型为string的构造函数
​
        Person p = (Person) c.newInstance("flx");//传递参数为"flx"
​
        System.out.println(p);
    }
​
    // 反射类私有的、有参的构造方法:private Person(int name)
    @Test
    public void test3() throws ClassNotFoundException, NoSuchMethodException,
            InstantiationException, IllegalAccessException,
            InvocationTargetException {
​
        Class clazz = Class.forName("com.shen.Person");
​
        Constructor c = clazz.getDeclaredConstructor(int.class);
        c.setAccessible(true);// 访问权限强制打开
        Person p = (Person) c.newInstance(1);
        System.out.println(p);
    }

4、获取方法

package com.shen2.reflect;
​
import java.lang.reflect.Method;
​
import org.junit.Test;
​
public class Demo3 {
    //反射方法


    //反射:public void eat()(无参)
    @Test
    public void test1() throws Exception{

        Person p = new Person();  //
        Class clazz = Class.forName("com.shen2.Person");  //完整名称
        Method method = clazz.getMethod("eat", null);  //eat,获取方法
        method.invoke(p, null);  //eat,执行
    }

    //反射:run(String address){(带一个参数)
    @Test
    public void test2() throws Exception{

        Person p = new Person();  //

        Class clazz = Class.forName("com.shen2.Person");  //完整名称
        Method method = clazz.getMethod("run", String.class);
        method.invoke(p, "北京");

    }

    //反射:public void run(String address,int num[],String ss[]){(多个参数)
    @Test
    public void test3() throws Exception{

        Person p = new Person();  //

        Class clazz = Class.forName("com.shen2.Person");  //完整名称
        Method method = clazz.getMethod("run", String.class,int[].class,String[].class);
        method.invoke(p, "上海",new int[]{1,2},new String[]{"1","2"});
    }


    //反射:public String test(String str) (带返回值)
    @Test
    public void test4() throws Exception{

        Person p = new Person();  //

        Class clazz = Class.forName("com.shen2.Person");  //完整名称
        Method method = clazz.getMethod("test", String.class);
        String result = (String) method.invoke(p, "xxxx");
        System.out.println(result);
    }

    //反射:private String test2(String str)  私有方法
    @Test
    public void test5() throws Exception{

        Person p = new Person();  //
        Class clazz = Class.forName("com.shen2.Person");  //完整名称
        Method method = clazz.getDeclaredMethod("test2", String.class);
        method.setAccessible(true);
        method.invoke(p, "");
    }

    //反射:public static String test3(String str){ 静态方法
    @Test
    public void test6() throws Exception{


        Class clazz = Class.forName("com.shen2.Person");  //完整名称

        Method method = clazz.getMethod("test3", String.class);
        String result = (String) method.invoke(null, "aaa");
        System.out.println(result);

    }

    //反射:public static void main(String[] args) {  反射main方法  
    //通过反射调用带数组的方法,要注意处理
    @Test
    public void test7() throws Exception{


        Class clazz = Class.forName("com.shen2.Person");  //完整名称

        Method method = clazz.getMethod("main", String[].class);
        method.invoke(null, (Object)new String[]{"1","2"});//main(String args[])
        //method.invoke(null, new Object[]{new String[]{"1","2"}});//main(String args[])


        //public Object invoke(Object obj, Object... args)  //jdk1.5
        //public Object invoke(Object obj, Object[] args)  //jdk1.4

        //public void run(String name,String password)  
        //method.invoke(p,new Object[]{"flx,123"})//1.4
        //method.invoke(p,"flx","123")
    }
}

5、获取字段

    //反射:public String name; 
    @Test
    public void test1() throws Exception{

        Person p = new Person();

        Class clazz = Class.forName("cn.itcast.reflect.Person");

        Field f = clazz.getField("name");  //name

        f.set(p, "flx");

        System.out.println(p.getName());

    }

    //反射:public String name; 
    @Test
    public void test2() throws Exception{

        Person p = new Person();
        p.setName("xxx");


        Class clazz = Class.forName("cn.itcast.reflect.Person");
        Field f = clazz.getField("name");  //name
        String result = (String) f.get(p);
        System.out.println(result);

    }

    //反射:public final String password = "";  //字段或成员变量
    @Test
    public void test3() throws Exception{

        Person p = new Person();

        Class clazz = Class.forName("cn.itcast.reflect.Person");
        Field f = clazz.getField("password");  //name
        String result = (String)f.get(p);
        System.out.println(result);

    }


    //反射:private int age; 私有字段
    @Test
    public void test4() throws Exception{

        Person p = new Person();

        Class clazz = Class.forName("cn.itcast.reflect.Person");
        Field f = clazz.getDeclaredField("age");
        f.setAccessible(true);

        f.set(p, 123);

        int result = (Integer) f.get(p);
        System.out.println(result);
    }
}

三、内省机制

1、通过Introspector操作bean属性

    //通过内省api操作bean的name属性
    @Test
    public void test1() throws Exception{

        Person p = new Person();

        PropertyDescriptor pd = new PropertyDescriptor("name",Person.class);//取出name
        Method method = pd.getWriteMethod();  //setName()
        method.invoke(p, "flx");

        //System.out.println(s.getName());
        method = pd.getReadMethod();   // getName
        String result = (String) method.invoke(p, null);
        System.out.println(result);

    }


    //操作bean的所有属性
    @Test
    public void test2() throws Exception{

        BeanInfo info = Introspector.getBeanInfo(Person.class);
        PropertyDescriptor pds[] = info.getPropertyDescriptors();//取出所有属性,所有函数继承Object故也会取出class(object中有getclass)
        for(PropertyDescriptor pd : pds){
            System.out.println(pd.getName());
        }

    }

2、通过beanutils工具包操作bean属性(常用)

     需要导入jar包

1.操作对象

Student.java

package com.shen.beanutils;
​
import java.util.Date;
​
public class Student {

    private String name;
    private String xx;
    private String password;
    private String email;
    private int age;

    private Date birthday;

    public Date getBirthday() {
        return birthday;
    }
​
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
​
    public String getPassword() {
        return password;
    }
​
    public void setPassword(String password) {
        this.password = password;
    }
​
    public String getEmail() {
        return email;
    }
​
    public void setEmail(String email) {
        this.email = email;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public String getXx() {
        return xx;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }

    public void setXx(String xx){
        this.xx = xx;
    }

    public void setYy(String yy){
    }
}

2.操作

1.简单获取和设置

    /**
     * 用beanUtils操作bean

     */
    public static void main(String[] args) throws IllegalAccessException, Exception {
​
        Student s = new Student();
        BeanUtils.setProperty(s, "name", "xiao");
        System.out.println(s.getName());
    }

2.运用例举

     在客户端传入多个参数后设置参数

        //传入的值
        String name = "flx";
        String password = "123";
        String age = "23";
        String email = "flx@sina.com";

        Student s = new Student();

        //设置多个属性
        BeanUtils.setProperty(s, "name", name);
        BeanUtils.setProperty(s, "password", password);
        BeanUtils.setProperty(s, "age", age);  //int(8种基本类型他会自动转换)
        BeanUtils.setProperty(s, "email", email);
        System.out.println(s.getAge());

3.复杂类型转换(时间转换)

        //传入的值
        String birthday = "1980-09-09";  //date

        Student s = new Student();

        //需要自己注册转换器
        //ConvertUtils.register(new DateLocaleConverter(), Date.class);//别人定义的转换器
        //自定义转换器
        ConvertUtils.register(new Converter(){//接口也可以new,但要实现抽象方法
​
            public Object convert(Class type, Object value) {  //"1980-09-09"

                if(value==null){
                    return null;
                }
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                Date date = null;
                try {
                    date = (Date) format.parse((String)value);
                } catch (ParseException e) {
                    throw new ConversionException(e);
                }
                return date;
            }


        }, Date.class);

        //设置多个属性
        BeanUtils.setProperty(s, "birthday", birthday);  //把string转换为date


        System.out.println(s.getBirthday());  //date*/
    }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

盡盡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值