每日筑基之反射&单元测试

反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。

1、反射第一步:加载类,获取类的字节码:Class对象

获取Class对象的三种方式:

1.直接使用类名.class获取:Class c1 = 类名.class

2.调用Class提供的方法:Class c2 = Class.forName("全类名")

3.调用Object提供的方法:Class c3 = 对象.getClass()

2.获取类的构造器

类中获取构造器的方法:

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

/*
获取构造器[下面是Class的方法]
    Constructor<?>[] getConstructors()	获取所有的公共构造器(只能获取public修饰的)
    Constructor<?>[] getDeclaredConstructors()	获取全部构造器(只要存在就能拿到)
    Constructor<T> getConstructor(Class<?>... parameterTypes)	获取某个公共构造器(只能获取public修饰的)
    Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)	获取某个构造器(只要存在就能拿到)

使用构造器(创建对象)[下面是Constructor的方法]
    T newInstance(Object... initArgs)	调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
    public void  setAccessible(boolean flag)	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰构造器反射创建对象,需要暴力反射(禁止JVM检查构造方法的访问权限)
*/
public class Demo2 {
	public static void main(String[] args)
			throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
		Class<Cat> catClass = Cat.class;
		// Constructor<?>[] getConstructors()	获取所有的公共构造器(只能获取public修饰的)
		Constructor<?>[] constructors = catClass.getConstructors();
		System.out.println(constructors.length);
		// Constructor<?>[] getDeclaredConstructors()	获取全部构造器(只要存在就能拿到)
		Constructor<?>[] declaredConstructors = catClass.getDeclaredConstructors();
		System.out.println(declaredConstructors.length);
		// Constructor<T> getConstructor(Class<?>... parameterTypes)	获取某个公共构造器(只能获取public修饰的)
		Constructor<Cat> constructor = catClass.getConstructor();//获取无参构造器
		System.out.println(constructor.getParameterAnnotations());
		System.out.println("===========");
		//   Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)	获取某个构造器(只要存在就能拿到)
		Constructor<Cat> declaredConstructor = catClass.getDeclaredConstructor(String.class,int.class);
		System.out.println(declaredConstructor.getParameterCount());//获取参数计数
		//使用构造器创建对象
		Cat cat = constructor.newInstance();
		System.out.println(cat);
		//暴力破解
		declaredConstructor.setAccessible(true);
		Cat cat1 = declaredConstructor.newInstance("鸡鸡",1);
		System.out.println(cat1);

	}

}

从类中获取构造器的方法:

获取类构造器的作用:初始化对象返回:

运行结果:

3.获取类的成员变量
从类中获取成员变量的方法:

获取到成员变量的作用

操作实例:



import java.lang.reflect.Field;

/*
获取成员变量[Class提供]
    public Field[] getFields()	获取类的所有公共成员变量(只能获取public修饰的)
    public Field[] getDeclaredFields()	获取类的全部成员变量(只要存在就能拿到)
    public Field getField(String name)	获取类的某个公共成员变量(只能获取public修饰的)
    public Field getDeclaredField(String name)	获取类的某个成员变量(只要存在就能拿到)

使用成员变量(赋值和取值) [Field提供]
    public void set(Object obj, Object value): 赋值
    public Object get(Object obj):	取值
    public void  setAccessible(boolean flag):	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰的变量,需要暴力反射
*/
public class Demo3 {
	public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
		Class<Cat> catClass = Cat.class;
		Field[] declaredFields = catClass.getDeclaredFields();
		System.out.println("变量个数"+declaredFields.length);
		for (Field declaredField : declaredFields) {
			System.out.println(declaredField.getName()+"-"+declaredField.getType());
		}
		Field a = catClass.getDeclaredField("a");
		System.out.println(a.getName()+"-"+a.getType());
		System.out.println("=======");
		Cat cat = new Cat();
		System.out.println(cat);
		int a1 = (int)a.get(cat);
		System.out.println(a1);
	}
}

4.获取类的成员方法
从类中获取成员方法的API:

成员方法的使用:

package com.itheima.b_反射;

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

/*
获取成员方法[Class提供]
    Method[] getMethods()	获取类的全部公共成员方法(只能获取public修饰的)
    Method[] getDeclaredMethods()	获取类的全部成员方法(只要存在就能拿到)
    Method getMethod(String name, Class<?>... parameterTypes) 	获取类的某个公共成员方法(只能获取public修饰的)
    Method getDeclaredMethod(String name, Class<?>... parameterTypes)	获取类的某个成员方法(只要存在就能拿到)

使用成员方法(执行方法)[Method提供]
    public Object invoke(Object obj, Object... args)	触发某个对象的该方法执行。
    public void  setAccessible(boolean flag)	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰的成员方法,需要暴力反射
*/
public class Demo4 {
	public static void main(String[] args)
			throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
		Class<Cat> catClass = Cat.class;
		//获取类的全部成员方法
		Method[] declaredMethods = catClass.getDeclaredMethods();
		System.out.println(declaredMethods.length);
		for (Method declaredMethod : declaredMethods) {
			System.out.println("方法名为"+declaredMethod.getName()+",返回类型为"+declaredMethod.getReturnType());
		}
		System.out.println("======");
		//获取某个类的成员方法
		Method method = catClass.getDeclaredMethod("eat",String.class);
		System.out.println(method.getReturnType());
		Class<?>[] parameterTypes = method.getParameterTypes();
		for (Class<?> parameterType : parameterTypes) {
			System.out.println(parameterType);
		}
		//触发某个对象的该方法执行
		Cat cat = new Cat();
		method.setAccessible(true);
		String str = (String)method.invoke(cat, "小鱼");
		System.out.println(str);
	}
}

3.反射的作用:

1.可以在运行时得到一个类的全部成分然后操作

2.可以破坏封装性,也可以破坏泛型的约束性,更重要的用途是适合:做Java高级框架

3.基本上主流框架都会基于反射设计一些通用技术功能

单元测试

单元测试:就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试。

Junit单元测试框架

可以用来对方法进行测试,它是由Junit公司开源出来的

优点:可以灵活的编写测试代码,可以针对某个方法执行测试,也支持一键完成对全部方法的自动化测试,且各自独立。 不需要程序员去分析测试的结果,会自动生成测试报告出来。

1.Junit框架快速入门:
为StringUtil创建一个测试类:

测试类中的测试方法一般取名为原方法+test

在方法上必须加上@Test

断言

断言是一种非常重要的功能,它用于验证测试中的一些条件是否为真。如果条件为真,那么测试通过;如果条件为假,那么测试失败。

常见断言assertEquals([String message],expected,actual):验证预期结果与实际结果是否相等。assertNotEquals([String message],expected,actual):验证预期结果与实际结果是否不相等。

参数说明:message(可选):将会在发生错误时报告这个消息。

expected(必填):期望值,通常都是用户指定的内容。

actual(必填):是被测试的代码返回的实际值。

运行结果:

2.Junit框架的常见注解
Junit单元测试框架的常用注解(Junit 4.xxxx版本)

在测试方法执行前执行的方法,常用于:初始化资源。

在测试方法执行完后再执行的方法,常用于:释放资源。

Junit单元测试框架的常用注解(Junit 5.xxxx版本)

这里我们以Junit-4.9版本为例

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值