java反射

反射:

类的加载

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

  1. 加载

就是指将class文件读入内存,并为之创建一个Class对象。

任何类被使用时系统都会建立一个Class对象

  1. 连接

验证 是否有正确的内部结构,并和其他类协调一致

准备 负责为类的静态成员分配内存,并设置默认初始化值

解析 将类的二进制数据中的符号引用替换为直接引用

  1. 初始化

就是我们以前讲过的初始化步骤

 

类加载器的组成

  1. Bootstrap ClassLoader 根类加载器

也被称为引导类加载器,负责Java核心类的加载

比如System,String等。在JDK中JRE的lib目录下rt.jar文件中

  1. Extension ClassLoader 扩展类加载器

负责JRE的扩展目录中jar包的加载。

在JDK中JRE的lib目录下ext目录

  1. System ClassLoader 系统类加载器

负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。

**********************************************************************

package reflect;

 

public class Person {

      

       public String name;

       private int age;

      

       public Person() {}

 

       private Person(String name) {

              this.name = name;

       }

       public Person(String name, int age) {

              this.name = name;

              this.age = age;

       }

 

      

       @Override

       public String toString() {

              return "Person [name=" + name + ", age=" + age + "]";

       }

 

       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;

       }

      

}

*************************************************************

获取类的三种方法:

package reflect;

/*

 * 获取一个类的class文件对象的三种方式

 *   1.对象获取

 *  2.类名获取

 *  3.class类的静态方法获取

 */

public class ReflectDemo {

       public static void main(String[] args) throws ClassNotFoundException {

              //1.对象获取

              Person p = new Person();

              //调用Person父类的方法getClass()

              Class c1 = p.getClass();

              System.out.println(c1.toString());

             

              //2.类名获取

              //每个类型包括静态和引用,都会赋予这个类型一个静态的属性,属性名字class

              Class c2 = Person.class;

              System.out.println(c2);

              System.out.println(c1==c2);

             

              //3.Class类的静态方法获取

              Class c3 = Class.forName("reflect.Person");

              System.out.println(c3);

       }

}

**********************************

获取类中的构造方法

 

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

 

public class ReflectDmeo2 {

       public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

              Class c = Class.forName("reflect.Person");

              //获取带有String和int参数的构造方法

              //getConstructor(参数列表)

              Constructor con = c.getConstructor(String.class,int.class);

              System.out.println(con);

              //con.newInstance(参数)

              Object b = con.newInstance("张三",12);//相当于new Person("张三",12);

              System.out.println(b.toString());

       }

}

**************************************************************************

获取类中构造方法的快捷方式

/*

 * 反射获取构造方法并运行,快捷方式

 * 要求:

 *   1.被反射的类必须有空参构造方法

 *   2.构造方法的权限必须是public

 */

public class ReflectDemo3 {

       public static void main(String[] args) throws Exception {

              Class c = Class.forName("reflect.Person");

              //Class类中定义方法,T newInstance() 直接创建被反射类的对象实例

              Object obj = c.newInstance();

              System.out.println(obj);

       }

}

****************************************

获取私有的构造方法

 

import java.lang.reflect.Constructor;

 

/*

 * 反射获取私有的构造方法

 * 不推荐,破坏了程序的封装性,安全性

 */

public class ReflectDemo4 {

       public static void main(String[] args) throws Exception {

              Class c = Class.forName("reflect.Person");

              //getDeclaredConstructors()    获取所有的构造方法,包括私有的

              Constructor[] cons = c.getDeclaredConstructors();

              for(Constructor con : cons) {

                     System.out.println(con);

              }

             

              Constructor con = c.getDeclaredConstructor(String.class);

              //setAccessible() Constructor的父类方法,值为true时,取消运行时期的权限检查

              con.setAccessible(true);

              Object obj = con.newInstance("zhangsan");

              System.out.println(obj);

       }

}

***********************************************************************

获取成员方法:

import java.lang.reflect.Method;

 

/*

 * 获取成员方法并运行

 */

public class ReflectDemo6 {

       public static void main(String[] args) throws Exception {

              Class c = Class.forName("reflect.Person");

              //Method[] getMethods() 获取的是class中所有的公共成员方法,包括继承的

             

              Method[] methods = c.getMethods();

              for(Method m : methods) {

                     System.out.println(m);

              }

       }

}

*********************************************************

泛型擦除

 

import java.lang.reflect.Method;

import java.util.ArrayList;

 

/*

 * 运用反射擦除泛型

 */

public class ReflectDemo7 {

       public static void main(String[] args) throws Exception {

              ArrayList<String> arr = new ArrayList<String>();

              arr.add("a");

              //想在arr中添加整数,通过反射实现

              Class c = arr.getClass();

              Method add = c.getMethod("add", Object.class);

              add.invoke(arr, 150);

              System.out.println(arr);

             

       }

}

 

*******************************************************************

反射配置文件

package cn.itcast.reflect;

 

public class Person {

       public void eat() {

              System.out.println("人在吃饭");

       }

}

package cn.itcast.reflect;

 

public class Student {

       public void study() {

              System.out.println("学生在睡觉");

       }

}

className=cn.itcast.reflect.Person

methodName=eat

 

package cn.itcast.reflect;

 

import java.io.FileReader;

import java.lang.reflect.Method;

import java.util.Properties;

 

public class Test {

       public static void main(String[] args) throws Exception {

              FileReader fr = new FileReader("config.properties");

              Properties pro = new Properties();

              pro.load(fr);

              fr.close();

              //通过键获取值

              String className = pro.getProperty("className");

              String methodName = pro.getProperty("methodName");

              //用反射获取类

              Class c = Class.forName(className);

              Object obj = c.newInstance();

              Method m = c.getMethod(methodName);

              m.invoke(obj);

             

       }

}

 

 

Junit单元测试:

       * 测试分类:

              1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值。

              2. 白盒测试:需要写代码的。关注程序具体的执行流程。

 

       * Junit使用:白盒测试

              * 步骤:

                     1. 定义一个测试类(测试用例)

                            * 建议:

                                   * 测试类名:被测试的类名Test       CalculatorTest

                                   * 包名:xxx.xxx.xx.test        cn.itcast.test

 

                     2. 定义测试方法:可以独立运行

                            * 建议:

                                   * 方法名:test测试的方法名           testAdd() 

                                   * 返回值:void

                                   * 参数列表:空参

 

                     3. 给方法加@Test

                     4. 导入junit依赖环境

 

              * 判定结果:

                     * 红色:失败

                     * 绿色:成功

                     * 一般我们会使用断言操作来处理结果

                            * Assert.assertEquals(期望的结果,运算的结果);

 

              * 补充:

                     * @Before:

                            * 修饰的方法会在测试方法之前被自动执行

                     * @After:

                            * 修饰的方法会在测试方法执行之后自动被执行

 

 

反射:框架设计的灵魂

       * 框架:半成品软件。可以在框架的基础上进行软件开发,简化编码

       * 反射:将类的各个组成部分封装为其他对象,这就是反射机制

              * 好处:

                     1. 可以在程序运行过程中,操作这些对象。

                     2. 可以解耦,提高程序的可扩展性。

 

 

       * 获取Class对象的方式:

              1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象

                     * 多用于配置文件,将类名定义在配置文件中。读取文件,加载类

              2. 类名.class:通过类名的属性class获取

                     * 多用于参数的传递

              3. 对象.getClass():getClass()方法在Object类中定义着。

                     * 多用于对象的获取字节码的方式

 

              * 结论:

                     同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

 

 

       * Class对象功能:

              * 获取功能:

                     1. 获取成员变量们

                            * Field[] getFields() :获取所有public修饰的成员变量

                            * Field getField(String name)   获取指定名称的 public修饰的成员变量

 

                            * Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符

                            * Field getDeclaredField(String name) 

                     2. 获取构造方法们

                            * Constructor<?>[] getConstructors() 

                            * Constructor<T> getConstructor(类<?>... parameterTypes) 

 

                            * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)  

                            * Constructor<?>[] getDeclaredConstructors() 

                     3. 获取成员方法们:

                            * Method[] getMethods() 

                            * Method getMethod(String name, 类<?>... parameterTypes) 

 

                            * Method[] getDeclaredMethods() 

                            * Method getDeclaredMethod(String name, 类<?>... parameterTypes) 

 

                     4. 获取全类名     

                            * String getName() 

 

 

       * Field:成员变量

              * 操作:

                     1. 设置值

                            * void set(Object obj, Object value) 

                     2. 获取值

                            * get(Object obj)

 

                     3. 忽略访问权限修饰符的安全检查

                            * setAccessible(true):暴力反射

 

 

 

       * Constructor:构造方法

              * 创建对象:

                     * T newInstance(Object... initargs) 

 

                     * 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

 

 

       * Method:方法对象

              * 执行方法:

                     * Object invoke(Object obj, Object... args) 

 

              * 获取方法名称:

                     * String getName:获取方法名

 

 

       * 案例:

              * 需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法

                     * 实现:

                            1. 配置文件

                            2. 反射

                     * 步骤:

                            1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中

                            2. 在程序中加载读取配置文件

                            3. 使用反射技术来加载类文件进内存

                            4. 创建对象

                            5. 执行方法

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值