目录

  • 概述
  • 什么是反射
  • 优缺点
  • Class类
  • 获得Class对象
  • 反射创建对象
  • 获取构造方法
  • 获取成员变量
  • 获取成员方法
  • 通过反射创建对象
  • 反射的应用
  • 序列化&反序列化


概述

什么是反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制

反射就是把java类中各个成分映射成一个个java对象也就是Class类对象

例如一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象

优缺点

优点
动态的获取实例,提高灵活性
缺点
性能较低,需要解析字节码,将内存中的对象解析

Class类

  • 一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被使用时都会创建一个Class对象
  • Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本信息

java反射遍历 list java反射和序列_开发语言

获得Class对象

public class Text {
    public static void main(String[] args) throws ClassNotFoundException {
        /*
            获取Class对象
        */

        //方式1:通过其class属性获取,任何数据类型(包括基本数据类型)都有一个“静态”的class属性
        Class c1 = Car.class;
        System.out.println(c1);

        //方式2:Object类里的getClass(),public final native Class<?> getClass(); native:本地方法(C++),操作系统实现
        Class c2 = new Car().getClass();

        //方式3:Class类的静态方法:forName(),根据类的地址将类的信息加载到内存中,并创建Class对象
        Class c3 = Class.forName("com.ff.dormitoryManage.reflect.Car");
    }
}

反射创建对象

T newInstance() 创建由此 类对象表示的类的新实例。
Car car1 = (Car) c1.newInstance();//创建了Class对象所表示的类的对象

获取构造方法

批量的方法

  1. public Constructor[] getConstructors():所有"公有的"构造方法
  2. public Constructor[] getDeclaredConstructors():获取所有的构造方法

获取单个的方法

  1. public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法:
  2. public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Text {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class c = Class.forName("com.ff.dormitoryManage.reflect.Car");
/*
 通过Class对象可以获取类中的构造方法

    1.获取构造方法:
 		1).批量的方法:
 			public Constructor[] getConstructors():所有"公有的"构造方法
            public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)

 		2).获取单个的方法,并调用:
 			public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
 			public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

 			调用构造方法:
 			Constructor-->newInstance(Object... initargs)
 */

        //获取所有的共有构造方法
        for (Constructor constructor : c.getConstructors()) {
            System.out.println(constructor);
        }

        //获取所有的构造方法
        for (Constructor declaredConstructor : c.getDeclaredConstructors()) {
            System.out.println(declaredConstructor);
        }

        //获取公有无参构造方法
        Constructor constructor = c.getConstructor();

        //获取私有构造方法
        Constructor declaredConstructor = c.getDeclaredConstructor(String.class, String.class);
        //修改权限(忽略访问修饰符)
        declaredConstructor.setAccessible(true);
        //调用构造方法创建对象
        Car car = (Car) declaredConstructor.newInstance("宝马", "红色");
    }
}

获取成员变量

批量的

  1. Field[] getFields():获取所有的"公有字段"
  2. Field[] getDeclaredFields():获取所有字段

单个的

  1. public Field getField(String fieldName):获取某个"公有的"字段;
  2. public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)

设置字段的值

Field --> public void set(Object obj,Object value):

参数说明: 1.obj:要设置的字段所在的对象 2.value:要为字段设置的值

package com.ff.dormitoryManage.reflect;

import java.lang.reflect.Field;

public class Text2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
        Class c = Class.forName("com.ff.dormitoryManage.reflect.Car");
        Car car = (Car) c.newInstance();
    /*
    获取成员变量并调用:

      1.批量的
      		1).Field[] getFields():获取所有的"公有字段"
      		2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
      2.获取单个的:
      		1).public Field getField(String fieldName):获取某个"公有的"字段;
      		2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)

      	 设置字段的值:
      		Field --> public void set(Object obj,Object value):
      					参数说明:
      					1.obj:要设置的字段所在的对象
      					2.value:要为字段设置的值

     */

        //获取所有共有的属性
        for (Field field : c.getFields()) {
            System.out.println(field);
        }

        //获取所有的属性
        for (Field declaredField : c.getDeclaredFields()) {
            System.out.println(declaredField);
        }

        //获取指定的属性并调用
        Field name = c.getField("name");
        name.set(car, "宝马");
        System.out.println(car);
        Field color = c.getDeclaredField("color");
        color.setAccessible(true);
        color.set(car, "黑色");
        System.out.println(car);
    }
}

获取成员方法

批量的

  1. public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
  2. public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)

获取单个

  1. public Method getMethod(String name,Class<?>... parameterTypes):
    参数:name : 方法名; Class … : 形参的Class类型对象
  2. public Method getDeclaredMethod(String name,Class<?>... parameterTypes)

调用方法

Method --> public Object invoke(Object obj,Object... args):

参数说明: obj : 要调用方法的对象; args:调用方式时所传递的实参

package com.ff.dormitoryManage.reflect;

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

public class text4 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class c = Class.forName("com.ff.dormitoryManage.reflect.Car");
        Car car = (Car) c.newInstance();

/*
获取成员方法并调用:

 1.批量的:
 		public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
 		public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
 2.获取单个的:
 		public Method getMethod(String name,Class<?>... parameterTypes):
 					参数:
 						name : 方法名
 						Class ... : 形参的Class类型对象
 		public Method getDeclaredMethod(String name,Class<?>... parameterTypes)

 	 调用方法:
 		Method --> public Object invoke(Object obj,Object... args):
 					参数说明:
 					obj : 要调用方法的对象;
 					args:调用方式时所传递的实参;

 */

        //获得成员方法
        Method run1 = c.getMethod("run");
        run1.invoke(car);
        Method run2 = c.getMethod("run", int.class);
        run2.invoke(car, 60);

        //获得get/set方法
        Field[] fields = c.getDeclaredFields();
        for (Field f : fields) {
            Method method = c.getMethod("get" + f.getName().substring(0, 1).toUpperCase() + f.getName().substring(1));
            method.invoke(car);
        }
    }
}

-------------------------------------------------------
公有无参构造方法
汽车跑
汽车以60码的速度跑
getName方法
getColor方法

通过反射创建对象

  1. 获取Class对象
  2. 根据Class对象 getConstructor()获得Constructor对象
  3. 根据Constructor对象的newInstance()获取反射类的对象
  4. 如果需要调用方法使用getMethod()获得Method对象
  5. 然后利用这个对象invoke()调用方法

反射的应用

JDBC 数据库连接

Spring框架

通过Xml加载Bean:

  1. 将Xml配置文件加载到内存中
  2. 解析文件中的内容
  3. 从配置文件中的类信息获取到这个类的Class对象
  4. 使用反射机制动态配置实例的属性

序列化&反序列化

序列化

Java对象—>字节序列

反序列化

字节序列—>Java对象

作用

  1. 便于在网络传输
  2. 本地保存和恢复,万一JVM停机了,通过反序列化可以恢复

java反射遍历 list java反射和序列_构造方法_02