- Junit单元测试
1. Junit白盒测试
2. 使用步骤:
a. 定义一个测试类(测试用例)
建议:测试类名:被测试类名+Test -- CaculatorTest
包名:xxx.xxx.xx.test
b. 定义测试方法:可以独立运行
建议:
方法名:test+测试的方法名 -- testAdd()
返回值:void
参数列表:空参
c. 给方法加上注解@Test
d. 导入junit依赖包
3. 判定结果:
不看程序输出,而使用断言Assert操作来处理结果
判定期望是否与程序结果一致
4. 当测试带有IO操作的程序时,时常需要申请资源,释放资源
建议:
定义个init()方法,用于所有测试的资源申请
在init()方法前加注解@Before
定义个close()方法,用于所有测试的资源释放
在close()方法前加注解@After -- 即使测试时抛出异常,close方法仍然会执行
- 反射
1. 反射是框架设计的灵魂
-- 框架:半成品软件。可以在框架的基础上进行软件开发
-- 反射:将类的各个组成部分封装为其他对象。
2. Java程序执行的三个阶段:
1. Source源代码阶段:由源代码 --> class字节码
2. 通过类加载器ClassLoader加载class文件
3. Class类对象阶段:
由class文件 --> Class类对象{
成员变量:Field[] fields
构造方法:Constructor[] cons
成员方法:Method[] methods
}
3. Runtime阶段:创建对象加载到内存中
3. 将成员变量封装为Field对象,将构造方法封装为Constructor对象,将成员方法封装为Method对象,这就指的是反射。
4. 作用:
1. 可以在程序的运行过程中操作这些对象 -- 代码提示
2. 可以解耦,提高程序可扩展性
- 获取Class对象
1. 在第一个阶段时:
Class.forName("全类名<包路径+'.'+类名>");
多用于配置文件,将类名定义在配置文件中。读取文件加载类
2. 在第二个阶段:
类名.class;
多用于参数的传递
3. 在第三个阶段:
对象.getClass();
多用于对象的方式获取字节码对象
- 使用Class对象
1. 获取功能:
a. 获取成员变量
1. Field[] getFields()
2. Field getField(String name)
3. Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
4. Field getDeclaredField(String name)
b. 获取构造方法们
1. Constructor<?>[] getConstructors()
2. Constructor<T> getConstructor(类<?>... parameterTypes)
3. Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
4. Constructor<?>[] getDeclaredConstructors()
c. 获取成员方法们:
1. Method[] getMethods()
2. Method getMethod(String name, 类<?>... parameterTypes)
3. Method[] getDeclaredMethods()
4. Method getDeclaredMethod(String name, 类<?>... parameterTypes)
d. 获取全类名
1. String getName()
2. String getPackage()
2. Field对象成员方法:
a. 获取成员变量的值
1. Field f = personClass.getFeild("变量名<a>");
2. Person p = new Person();
3. Object value = f.get(p);
b. 设置成员变量值
4. f.set(对象名, 成员变量a要设置的值);
3. 暴力反射
由于getDeclaredField成员方法可以获取私有成员变量
但是,直接对私有成员变量使用get/set方法时,会抛出异常,提示非法权限
因此,需要忽略权限设置,使用成员方法setAccessible忽略
f.setAccessible(true);
对于成员方法和构造方法对象中同样有该成员方法
4. Constructor对象成员方法:
a. 创建对象:
T newInstance(Object ... initargs);
例如:
Constructor cons = personClass.getConstructor(String.class, int.class);
Object p = cons.newInstance("nameXXX",12);
5. Method对象成员方法:
a. 执行方法:
Object invoke(Object obj, Object... args);
例如:
Method eat = personClass.getMethod("eat");
Person p = new Person();
eat.invoke(p);
Method eat2 = personClass.getMethod("eat", String.class);
eat2.invoke(p,"args");
b. 获取方法名称:
String getName()
例如:
eat.getName();
- 实现一个小框架
1. 实现步骤:配置文件 --> 反射
a. 将需要创建类型的全类名和需要执行的方法定义在一个配置文件中
b. 在程序中加载读取配置文件
c. 利用反射技术加载类文件进内存
d. 创建类对象
e. 执行方法
2. 例如:
psvm{
Properties pro = new Properties();
ClassLoader cld = ReflectTest.class.getClassLoader();
InputStream is = cld.getResourceAsStream("pro.properties");
pro.load(is);
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
Class cls = Class.forName(className);
Object obj = cls.newInstance();
Method method = cls.getMethod(methodName);
method.invoke(obj);
}
配置文件pro.properties
className=xx.xx.Person
methodName=eat
- 注解
1. JDK 1.5+一种代码级别的说明。声明在包,类,字段,方法,局部变量,方法参数等前面,用来说明
2. 作用:
编写文档:通过代码内标识的注解生成文档<API文档> -- 使用javadoc命令
代码分析:通过注解对代码进行分析 -- 使用反射抽取注解
编译检查:例如<@Override>
3. 预定义注解:
@Override:检测被该注解标注的方法是否继承自父类
@Deprecated:该注解标注的内容表示已经过时 -- 用于兼容低版本
@SuppressWarnings:压制警告 -- @SuppressWarnings("all")压制所有警告
4. 自定义注解:
a. 格式:
元注解
public @interface 自定义注解名{
}
b. 本质:
注解本质上是一个接口
pubic interface 注解名 extends Annotation {}
c. 属性:注解中的成员变量和方法
1. 属性的返回值类型:
基本数据类型/String/枚举/注解/以上类型的数组
2. 定义了属性后,在使用时需要给属性赋值
-- 也可以在定义时标注默认值,使用default关键字
-- String name() default "testName";
-- 如果只有一个属性需要复制,且属性名为value,则在使用时可以不标注属性名
public @interface SuppressWarnings{
String[] value();
}
在使用时直接标注@SuppressWarnings("all")
完整为@SuppressWarnings(value = "all")
多个值的使用逗号分隔
d. 元注解:用于描述注解的注解
@Target:描述注解能够作用的位置
ElementType取值:
TYPE:表示可以作用于类上
METHOD:表示可以作用与方法上
FIELD:表示可以作用与成员变量上
@Retention:描述注解被保留的阶段 -- Java代码的三个阶段
RetentionPolicy取值:
SOURCE:表示注解不会保留到class字节码中
CLASS:表示注解会保留到class字节码文件中,不会被JVM读取
RUNTIME:表示注解会保留到class字节码文件中,并被JVM读取
@Documented:描述注解是否被抽取到API文档中
@Inherited:描述该注解是否被子类继承
5. 获取注解属性的值
a. 获取注解定义位置的对象 -- 即Class,Method,Field对象,它们中都有成员方法getAnnotation
b. 通过对象成员方法getAnnotation获取指定注解对象
c. 通过注解对象调用成员方法获取属性值