Java 反射

目录

为什么需要java反射?

回顾之前java中如何使用类和对象

反射:

概念:

提出问题:

        如何获得类的信息? 

        如何获得类的Class对象?

  获得类的Class对象后,如何获取类信息并操作对象中的成员?

1.获取类中的构造方法信息

    2.获得成员变量

实例验证:


为什么需要java反射?

        在编写代码的时候,当你仅仅知道一个类名,并且想要动态得到类的定义消息,包含的方法和属性等的时候,我们就需要通过java反射来获得这些.由于像框架,tomcat,或者一些其他的组件(jackson 对象-->json),事先不知道是哪个类,只能根据配置文件中配置的类的地址决定要创建并且操作哪一个类.

回顾之前java中如何使用类和对象

1.定义类
      public class Car{
        String name;
        .....
        public void run(){}

      }
2.创建已知类的对象,明确知道要创建哪个类的对象
        Car car = new Car();

        一切都是已知的,这对于我们自己写的程序时没有任何问题(业务代码)
        但是像框架,tomcat,或者一些其他的组件(Jackson  对象-->json),事先是不知道具体处理哪些类的,只能根据配置文件中配置的类的地址决定要创建并操作哪一个类

        框架要做到可以处理任何类,只要写一套处理程序即可
        框架要做到以不变应万变
    
    问题:如果我们只知道类的地址,如何使用类

    框架可以做到给他什么类名,就可以创建给定类的对象,并调用该对象的方法和属性
    (1)创建对象
    (2)将查询到的结果,封装到创建的对象中(调用setxxx(),调用xxx属性)

    如何做到写一套程序可以处理任何类
    答案是:反射机制

    反射机制,可以看做是一种反向使用类

反射:

概念:

          在程序运行状态中,可以动态获取类的信息,可以动态创建类的对象,可以调用类的成员(变量,方法,构造方法)的机制称为java反射机制


提出问题:

        如何获得类的信息? 

        可以通过获取到类的Class对象,然后通过Class独享就可以获得类中想要的信息

        如何获得类的Class对象?

        1.方式1   框架中常用的,只知道类的字符串地址
            Class c = Class.forName("com.ffyc.javareflect.demo2.User")
        2.方式2   类名.class    获得类的Class对象
            Admin.class
        3.方式3      适用的场景      是已知对象,需要对任何对象进行操作
            User user=new User();
            Car car=new Car();

           Class c1=user.getClass();
           Class c2=car.getClass();

package com.ffyc.javareflect.demo2;

import com.ffyc.javareflect.demo1.Car;

public class Test2 {
    public static void main(String[] args) throws ClassNotFoundException {
        //方式1
        String s="com.ffyc.javareflect.demo2.User";
        Class c1 = Class.forName(s);//把给定的地址类进行了加载,为其创建Class对象
        Class c2 = Class.forName(s);//把给定的地址类进行了加载,为其创建Class对象
        System.out.println(c1);
        System.out.println(c1==c2);

        //通过类的Class对象,就可以任意获取类中的信息
        c1.getFields();

        c1.getMethods();

        c1.getConstructors();


        //方式2
        Class c3=User.class;
        System.out.println(c2==c3);

        //方式3
        User user=new User();
        Car car=new Car();

        Class c4=user.getClass();//通过已知的对象中的getClass  获得该对象的Class对象
    }
}

  获得类的Class对象后,如何获取类信息并操作对象中的成员?

1.获取类中的构造方法信息

 获得指定(参数个数,类型)的公共构造方法,返回Constructor来表示获得到的构造方法
        Constructor  getConstructor(类<?>... parameterTypes)  获得指定(参数个数,类型)的公共构造方法
              newInstance()   创建类的对象
        Constructor[]    getConstructors()   返回所有公共的构造方法
        Constructor<T>   getDeclaredConstructor(类<?>... parameterTypes)   获得指定的构造方法(包含私有,受保护,默认,公共)
        Constructor<?>[]   getDeclaredConstructors()  获得所有的构造方法

        getConstructor()和getDeclaredConstructor()方法:

        两个方法如果不传参数的话,就会自动调用无参构造方法,而在框架中,框架在通过反射获得类的对象的时候,就是默认调用无参构造方法,所以当我们定义了有参构造方法后,必须定义一个无参构造方法来满足后面框架的需求.如果想要获得有参的构造方法,我们需要在调用方法的时候在参数里写入所需的参数类型的class类.

        两个方法在功能上是一致的,都是为了获得类的构造方法,但是区别是getConstructor只能获得该类中的公共方法,而getDeclaredConstructor看可以获得该类中的所有方法,包含私有方法.        

package com.ffyc.javareflect.demo2;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test3 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        String s="com.ffyc.javareflect.demo2.User";

        //创建对象方式
            //new
            //流   反序列化
            //反射


        //加载类,并获得类的Class对象
        Class c=Class.forName(s);
        /*
            1.通过Class类的对象创建对象
                Object userobject=c.newInstance();
            2.获取类中的构造方法信息,通过构造方法中的newInstance()创建对象
                Constructor constructor = c.getConstructor();
                Object userobject = constructor.newInstance();
        * */


        //通过Class类的对象创建User对象
        //Object userobject=c.newInstance();
        //System.out.println(userobject);

        //获取类中的构造方法信息
        Constructor constructor = c.getConstructor();//获得类中指定的公共构造方法,将获得到的无参构造方法封装到一个Constructor中
        Object userobject = constructor.newInstance();//通过构造方法中的newInstance()创建对象
        System.out.println(userobject);

        Constructor constructor1 = c.getDeclaredConstructor();//获得类中指定的构造方法(包含私有)


        Constructor constructor2=c.getConstructor(String.class,String.class);//获得公共的有参构造方法
        Object userobject1 = constructor2.newInstance("111","222");//创建对象,并为对象属性赋值
        //向下转型
        User user=(User) userobject1;
        System.out.println(user);

        Constructor[] constructors = c.getConstructors();//获得所有的公共的构造方法
        Constructor[] constructors1 = c.getDeclaredConstructors();//获得所有的构造方法(包括私有)
        System.out.println(constructors.length);
        System.out.println(constructors1.length);
    }
}

    2.获得成员变量

        Field field = getField(String name);  获得指定名字的公共属性,返回Field对象  表示获得属性
        Field[] fields = getFields();  获得所有的公共的属性
        Field field = getDeclaredField(String name);   获得指定名字的属性(包含私有)
        Field[] fields = getDeclaredFields();  获得所有属性(包含私有)

        getFields()和getDeclaredFields()方法

        两个方法都是用于获取类的属性,但是getFields()只能获得该类的所有公共属性,但是getDeclaredFields()可以获得该类中的所有属性(包括私有属性).

package com.ffyc.javareflect.demo2;

import java.lang.reflect.Field;

public class Test4 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        String s="com.ffyc.javareflect.demo2.User";

        Class c=Class.forName(s);//获得类的Class对象

        Object userobject = c.newInstance();//创建User类的对象

        //获得类中的成员变量
        //获得类中指定的公共的属性,把属性封装到一个Field对象中
        //Field field = c.getField("userName");
        //获得类中指定的的属性(包含私有,受保护,默认,公共),把属性封装到一个Field对象中
        Field userfield = c.getDeclaredField("userName");

        //Field[] fields = c.getFields();
        //System.out.println(fields.length);

        //获得到所有的属性(包含私有的)
        Field[] fields = c.getDeclaredFields();
        System.out.println(fields.length);

        //循环所有的属性,为属性赋值
        for (Field f:fields){
            f.setAccessible(true);//设置私有属性可以操作
            f.set(userobject, "111");
        }
        System.out.println(userobject);
    }
}


    3.获得方法
        getMethods();        获得本类和父类中所有公共的成员方法

        getDeclaredMethods();        获得本类中所有的成员方法

package com.ffyc.javareflect.demo2;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test5 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
        String s="com.ffyc.javareflect.demo2.User";

        Class c=Class.forName(s);//获得类的Class对象

        Object userobject = c.newInstance();//创建User类的对象

        Method eat = c.getMethod("eat");
                //执行userobject对象中的 无参的eat方法
               eat.invoke(userobject );
        Method eat1=c.getMethod("eat", String.class);
               eat1.invoke(userobject, "烤肉");


        Method[] methods = c.getMethods();//获得本类和父类中所有公共的成员方法
        Method[] methods1 =  c.getDeclaredMethods();//获得本类中所有的成员方法

        System.out.println(methods.length);//15
        System.out.println(methods1.length);//7
    }
}

实例验证:

自定义的对象转json方法

package com.ffyc.javareflect.util;

import com.ffyc.javareflect.demo1.Car;
import com.ffyc.javareflect.demo2.User;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class JsonUtil {
    /*
    自定义的对象转json方法
    * */

    public String objectToJson(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String json = "{";
        Class c=object.getClass();//获得对象类的Class对象
        //获得对象中所有私有属性
        Field[] declaredFields=c.getDeclaredFields();

        for(Field f:declaredFields){
            //生成属性的get方法名字
            //String get="get"+(String.valueOf(f.getName().charAt(0))).toUpperCase()+f.getName().substring(1);
            String get="get"+(char)(f.getName().charAt(0)-32)+f.getName().substring(1);
            System.out.println(get);
            Method getMethod = c.getMethod(get);//通过get方法名,获得方法

            json+=f.getName()+":"+getMethod.invoke(object)+",";
        }
        json=json.substring(0,json.length()-1);
        json+="}";
        return json;
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        User user=new User();
            user.setUserName("admin");
            user.setPassword("111");
        Car car=new Car();
            car.setName("奔驰");
            car.setColor("黑色");
        System.out.println(new JsonUtil().objectToJson(user));
        System.out.println(new JsonUtil().objectToJson(car));
    }
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值