目录
⚫单元测试:就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此单元测试就是针对Java方法的测试。
1️⃣单元测试
①单元测试的概述
⚫单元测试:就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此单元测试就是针对Java方法的测试。
②单元测试的快速入门
/**
* 测试类
*/
public class TestUserService {
/**
测试方法
注意点:
1.必须是公开的,无参数,无返回值的方法
2.测试方法必须使用@Test注解标记
*/
@Test
public void testLoginName(){
UserService userService = new UserService();
String rs = userService.loginName("admin","123456");
//进行预期结果的正确性测试:断言
Assert.assertEquals("您的功能可能出现问题","登录成功",rs);
}
@Test
public void testSelectNames(){
UserService userService = new UserService();
userService.selectNames();
}
}
③单元测试的常用注解
2️⃣反射
①反射概述
⚫反射是指对于任何一个class类,在运行的时候都可以得到这个类的全部成分
⚫可以得到这个类的构造器对象(constructor)、成员变量对象(Filed)、成员方法对象(Method)
反射的关键:
反射的第一步就是得到编译后的class对象,人后就可以得到其所有成分。
②反射获取类对象
/*
目标:反射第一步:获取class对象
*/
public class Test {
public static void main(String[] args) throws Exception {
//1.class类中的一个静态方法 :forName(全限名:包名+类名)
Class c = Class.forName("com.study.d2_reflect_class.Student");
System.out.println(c);
//2.类名.class
Class c1 = Student.class;
System.out.println(c1);
//3.对象.getClass() 获取对象对应类的Class对象
Student s = new Student();
Class c2 = s.getClass();
System.out.println(c2);
}
}
③反射获取构造器对象
public class TestStudent01 {
//1.getConstructors:获取全部构造器(public)
@Test
public void getConstructors(){
//a第一步:获取类对象
Class c = Student.class;
//b第二步:提取类中的全部构造器对象
Constructor[] constructors = c.getConstructors();
//c遍历构造器
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + "====>" + constructor.getParameterCount());
}
}
//2.getDeclaredConstructors() 全部构造器
@Test
public void getDeclaredConstructors(){
//a第一步:获取类对象
Class c = Student.class;
//b第二步:提取类中的全部构造器对象
Constructor[] constructors = c.getDeclaredConstructors();
//c遍历构造器
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + "====>" + constructor.getParameterCount());
}
}
//3获取单个构造器getConstructor
@Test
public void getConstructor() throws Exception {
//a第一步:获取类对象
Class c = Student.class;
//b定位单个构造器(按照参数定位午餐构造器)
Constructor cons = c.getConstructor();
System.out.println(cons.getName() + "====>" + cons.getParameterCount());
}
//4.getDeclaredConstructor
@Test
public void getDeclaredConstructor() throws Exception {
//a第一步:获取类对象
Class c = Student.class;
//b定位单个构造器(按照参数定位午餐构造器)
Constructor cons = c.getDeclaredConstructor();
System.out.println(cons.getName() + "====>" + cons.getParameterCount());
//c定位有参数构造器
Constructor cons1 = c.getDeclaredConstructor(String.class,int.class);
System.out.println(cons1.getName() + "====>" + cons1.getParameterCount());
}
}
public class TestStudeng02 {
@Test
public void getDeclaredConstructor() throws Exception {
//1.调用构造器得到一个类的对象返回
//a第一步:获取类对象
Class c = Student.class;
//b定位单个构造器(按照参数定位无参构造器)
Constructor cons = c.getDeclaredConstructor();
System.out.println(cons.getName() + "====>" + cons.getParameterCount());
Student s = (Student) cons.newInstance(); //根据指定的构造器创建对象
System.out.println(s);
//c定位有参数构造器
Constructor cons1 = c.getDeclaredConstructor(String.class,int.class); //传的是参数类型
System.out.println(cons1.getName() + "====>" + cons1.getParameterCount());
Student s1 = (Student) cons1.newInstance("哇哈哈",1000);
System.out.println(s1);
}
}
④反射获取成员变量对象
public class FieldDemo1 {
@Test
public void getDeclaredFields(){
//a定位class对象
Class c = Student.class;
//b获取所有成员变量
Field[] fields = c.getDeclaredFields();
//遍历
for (Field field : fields) {
System.out.println(field.getName() + "--->" + field.getType());
}
}
@Test
public void getDeclaredField() throws Exception {
//a定位class对象
Class c = Student.class;
//b获取某个成员变量
Field f = c.getDeclaredField("age");
System.out.println(f.getName() + "-->" + f.getType());
}
}
public class FieldDemo2 {
@Test
public void getDeclaredField() throws Exception {
//a定位class对象
Class c = Student.class;
//b获取某个成员变量
Field ageF = c.getDeclaredField("age");
ageF.setAccessible(true); //暴力打开权限
//c赋值
Student s = new Student();
ageF.set(s,18); //s.setAge(18)
System.out.println(s);
//d取值
int age = (int) ageF.get(s);
System.out.println(age);
}
}
⑤反射获取方法对象
public class Dog {
private String name;
public Dog(String name) {
this.name = name;
}
public void run(){
System.out.println("狗刨的快");
}
public void eat(){
System.out.println("狗吃骨头");
}
public String eat(String name){
System.out.println("狗吃" + name);
return "吃得很开心";
}
public static void inAdd(){
System.out.println("一群单身狗");
}
public Dog() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class MethodDemo1 {
@Test
public void getDeclareMethods(){
//a获取类
Class c = Dog.class;
//b获取全部方法
Method[] methods = c.getDeclaredMethods();
//c遍历
for (Method method : methods) {
System.out.println(method.getName() + " 参数个数" + method.getParameterCount());
}
}
@Test
public void getDeclareMethod() throws Exception {
//a获取类
Class c = Dog.class;
//b获取单个方法
Method me1 = c.getDeclaredMethod("eat");
Method me2 = c.getDeclaredMethod("eat",String.class);
me1.setAccessible(true);
me2.setAccessible(true);
//c出发方法的执行
Dog d = new Dog();
//注意:方法如果没有返回值,那么返回的是null
Object resault = me1.invoke(d);
System.out.println(resault);
Object resault2 = me2.invoke(d,"骨头");
System.out.println(resault2);
}
}
⑥反射的作用--绕过编译阶段为集合添加数据
public class ReflectDemo {
public static void main(String[] args) throws Exception {
//需求:反射实现泛型擦除后,加入其他类型的元素
ArrayList<String> list1 = new ArrayList<>();
ArrayList<Integer> list2 = new ArrayList<>();
System.out.println(list1.getClass());
System.out.println(list2.getClass());
System.out.println(list1.getClass() == list2.getClass()); //Arraylist.class
System.out.println("--------------------------");
ArrayList<Integer> list3 = new ArrayList<>();
list3.add(11);
list3.add(12);
Class c = list3.getClass(); //Arrraylist.class ==> public booolean add(E e)
Method add = c.getDeclaredMethod("add", Object.class);
boolean rs = (boolean) add.invoke(list3,"哇哈哈");
System.out.println(rs);
System.out.println(list3);
}
}
⑦反射的作用--通用框架的底层原理
public class MybatiesUtiles {
/**
* 保存任意类型的对象
* @param obj
*/
public static void save(Object obj){
try (PrintStream ps = new PrintStream(new FileOutputStream("junit-reflect-annnotation-proxy-app\\src\\data.txt",true));){
//1.提取这个对象的全部成员变量,只有反射可以解决
Class c = obj.getClass();
ps.println("============"+ c.getSimpleName() + "==============");
//2.提取他的全部成员变量
Field[] fields = c.getDeclaredFields();
//3.获取成员变量信息
for (Field field : fields) {
String name = field.getName();
//取值
field.setAccessible(true);
String value = field.get(obj) + "";
ps.println(name + "=" + value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ReflectDemo {
public static void main(String[] args) {
Student s = new Student("哇哈哈",'女',19);
MybatiesUtiles.save(s);
Teacher t = new Teacher("朱老大三",33,100000);
MybatiesUtiles.save(t);
}
}
3️⃣注解
public @interface NyBook {
String name();
String[] authors();
double price();
}
@Target({ElementType.METHOD,ElementType.FIELD}) //元注解
@Retention(RetentionPolicy.RUNTIME) //一直活着 在运行阶段也不消失
public @interface MyTest {
}
4️⃣动态代理
public class StarAgentProxy {
/**
设计一个方法来返回一个明星对象的代理对象
*/
public static Skill getProxy(Star obj ){
//为杨超越生成一个代理对象
/**
* public static Object newProxyInstance(ClassLoader loader, 类加载器
* Class<?>[] interfaces, 对象实现的接口列表
* InvocationHandler h)
*/
return (Skill) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("收到首付款");
//真正的让杨超月去唱歌跳舞
//method正在调用的方法对象 args代表这个方法的参数
Object rs = method.invoke(obj,args);
System.out.println("尾款收到");
return rs;
}
});
}
}
public class Test {
public static void main(String[] args) {
//目标:理解动态代理的执行流程,学习并开发一个代理对象出来
//1创建一个对象,对象的类必须实现接口
Star s = new Star("杨超越");
//为杨超越对象生成一个代理对象(经纪人)
Skill s2 = StarAgentProxy.getProxy(s);
s2.jump();
s2.sing();
}
}