单元测试
含义:最小的功能单元编写测试代码(Java的方法)
优点: 一键执行;生测试报告(绿色正常,红色报错);执行不影响其他的测试方法
怎么做: 1.使用Junit4.jar导入到库中;2.@Test注解(1.公开的、无参数、无返回值;2.主要在方法上注解)3.Assert 断言 判断 方法是否有问题
反射
含义:对于任意一个Class类,在"运行的时候"都可以得到这个类的全部成分如Constructor Field Method
优点: Java语言的反射机制:动态获取类信息和动态调用类中成分的能力
怎么做:获取Class类对象
// 1.通过类名.Class
Class<Student> studentClass = Student.class;
System.out.println(studentClass); //Student.class
// 2.通过类的静态方法:forName(全限名:包名+类名)
Class<?> forName = Class.forName("com.lyi.d2_reflect_create.Student");
System.out.println(forName);
// 3.通过对象自身的方法 对象.getClass
Student student = new Student("张三");
System.out.println(student.getClass());
// class com.lyi.d2_reflect_create.Student
获取类构造器对象
获取所有公共构造函数
// 1.获取Class对象
Class<?> aClass = Student.class;
// 2.包含一个数组 Constructor对象反射由此表示的类的所有公共构造函数
Constructor<?>[] constructors = aClass.getDeclaredConstructors();
// 3.遍历所有的公共的构造函数
for (Constructor<?> constructor : constructors) {
System.out.println("构造器名称:" + constructor.getName() +
";构造器的参数个数:" + constructor.getParameterCount());
获取指定的构造函数
//通过有参构造器获取对象
Class<Student> studentClass2 = Student.class;
// parameterTypes – 参数数组 返回值:具有指定参数列表的构造函数的Constructor对象
Constructor<Student> cons2 = studentClass2.getDeclaredConstructor(String.class,int.class);
System.out.println(cons2.getName()+"\t" + cons2.getParameterCount());
//initargs – 作为参数传递给构造函数调用的对象数组 返回值:通过调用此对象表示的构造函数创建的新对象
Student student1 = cons2.newInstance("张三" ,500);
获取成员变量
//获取所有成员变量
Class<Student> studentClass = Student.class;
//返回值 表示该类的所有声明字段的Field对象数组
for (Field field : studentClass.getDeclaredFields()) {
System.out.println(field.getName()+ "\t" + field.getType());
}
//获得指定成员变量
Class<Student> studentClass1 = Student.class;
//name – 字段的名称 返回值此类中指定字段的Field对象
Field declaredField = studentClass1.getDeclaredField("age");
System.out.println(declaredField.getName()+ "\t" + declaredField.getType());
//给成员变量赋值和取值
Class<Student> studentClass = Student.class;
Field ageF = studentClass.getDeclaredField("age");
// 暴力打开私有成员的变量的访问大小
ageF.setAccessible(true);
Student student = new Student();
// 设置成员变量的值
//参数:obj - 应修改其字段的对像 value – 被修改的obj字段的新值
ageF.set(student,20);
//获得成员变量的值
System.out.println(ageF.get(student));
获取成员方法
//通过getDeclaredMethods获取所有方法
Class<Dog> dogClass = Dog.class;
//返回Method对象的数组,表示该类的所有声明的方法
for (Method declaredMethod : dogClass.getDeclaredMethods()) {
System.out.println(declaredMethod.getName() + ": " + declaredMethod.getParameterCount());
}
//通过getDeclaredMethod获取指定方法
Class<Dog> dogClass = Dog.class;
//name – 方法的名称 parameterTypes – 参数数组回报: 与指定名称和参数匹配的此类方法的Method对象
Method method1 = dogClass.getDeclaredMethod("buy", String.class);
method1.setAccessible(true);
Dog dog1 = new Dog();
//obj – 调用底层方法的对象 args – 用于方法调用的参数 回报:使用参数args在obj上调度此对象表示的方法的结果
Object result2 = method1.invoke(dog1, "衣服");
System.out.println(result2);
绕过编译阶段给集合添加数据
//ArrayList 在编译阶段 移除泛型
ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList<String> list2 = new ArrayList<String>();
System.out.println(list.getClass()==list2.getClass());
ArrayList<Integer> list3 = new ArrayList<Integer>();
list3.add(1);
list3.add(2);
//获取class对象
Class<? extends ArrayList> genericityClass = list3.getClass();
// public boolean add(E e) 利用反射获取这个add方法 和 成员变量
Method add = genericityClass.getDeclaredMethod("add", Object.class);
boolean rs = (boolean) add.invoke(list3, "白马");
System.out.println(rs);
利用反射,手动编译动态方法
//把代码放在try()里面 可以不用关闭流操作
try (
FileOutputStream fos = new FileOutputStream("day04-junit-reflect-annotation-proxy- app/src/testOverride.txt",true);
PrintStream printStream = new PrintStream(fos))
{
// 1.定义一个方法,可以接收任意类的对象
Class<Object> objectClass = (Class<Object>) obj.getClass();
printStream.println("=============="+ objectClass.getSimpleName() +"==============");
// 2.每次收到一个对象后,需要解析这个对象的全部成员变量名称
for (Field declaredField : objectClass.getDeclaredFields()) {
declaredField.setAccessible(true);
// 3.遍历成员变量信息,然后提取本成员变量在对象中的具体值
Object fieldName = declaredField.getName();
Object fieldValue = declaredField.get(obj);
System.out.println(fieldName + "=" + fieldValue);
//4.存入成员变量名称和值到文件中去即可
printStream.println(fieldName + "=" + fieldValue);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
注解
含义: 标注,Jdk1.5的注释机制
作用: 对Java中的类、方法、成员变量作标记,然后做特殊处理
怎么做:
自定义注解
格式:
public @interface 注解名称{
public 属性类型 属性名() default 值;
}
如
元注解
含义:注解加注解
怎么做:
@Retention(RetentionPolicy.RUNTIME)
//指示注释类型适用的上下文。 只能在方法和类的类型上也就是class对象
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface Book{
public String value();
public double price() default 100.0;
public String[] authors() ;
}
注解的解析:
含义:是否存在注解,存在就解析出内容
怎么做:
//获取注解在类上面的数据
// 1.先得到类对象
Class<BookStore> bookStoreClass = BookStore.class;
// 2.判断这个类上面是否有注解类 参数: annotationClass——注解类型对应的Class对象
if (bookStoreClass.isAnnotationPresent(Book.class)) {
// 3.获取该注解对象 参数: annotationClass——注解类型对应的Class对象
Book declaredAnnotation = bookStoreClass.getDeclaredAnnotation(Book.class);
System.out.println(declaredAnnotation.value());
System.out.println(declaredAnnotation.price());
System.out.println(Arrays.toString(declaredAnnotation.authors()));
//获取注解在方法上面的数据
// 1.先得到类对象
Class<BookStore> bookStoreClass2 = BookStore.class;
// 1.1 获取这个类的下面指定的方法
Method run = bookStoreClass2.getDeclaredMethod("run");
// 2.判断这个类上面是否有注解类
if (run.isAnnotationPresent(Book.class)) {
// 3.获取该注解对象
Book declaredAnnotation = run.getDeclaredAnnotation(Book.class);
System.out.println(declaredAnnotation.value());
System.out.println(declaredAnnotation.price());
System.out.println(Arrays.toString(declaredAnnotation.authors()));
//执行注解的方法
AnnotationDemo2 demo = new AnnotationDemo2();
Class aClass = AnnotationDemo2.class;
Method[] methods = aClass.getDeclaredMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(Mytest.class)) {
// name-->对象 反射 对象.方法
method.invoke(demo);
}
}
动态代理
代理:某些情况下对象会找一些代理对象,替他完成额外的工作,如明星(经纪人)
-
先有接口Sing这个动作
-
对象实现这个接口,并且重写这个方法的内容
-
通过Proxy.newProxyInstance(ClassLoader,Interface,Handle),得到对象的代理对象
-
通过代理方法获取代理类,然后调用接口里面的方法
//关键代理类方法 /** * Object newProxyInstance(ClassLoader loader, * Class<?>[] interfaces, * InvocationHandler h) * loader – 定义代理类的类加载器 interfaces – 代理类要实现的接口列表 h - 将方法调用分派到的调用处理程序 */ return (Skill) Proxy.newProxyInstance(star.getClass().getClassLoader(), star.getClass().getInterfaces(), new InvocationHandler() { //method – Method实例对应于代理实例上调用的接口方法。 //obj – 调用底层方法的对象 args – 一个对象数组,其中包含在代理实例上的方法调用中传递的参数值 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("收定金"); Object rs = method.invoke(star); System.out.println("收尾款,并且把杨接回来!!"); return rs; } }); }
手动编写动态代理练习
//核心动态代理编码 public static <T> T getProxyUserService(T obj) { return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime = System.currentTimeMillis(); Object rs = method.invoke(obj, args); long endTime = System.currentTimeMillis(); System.out.println(method.getName() + "耗时:" + (endTime - startTime)/1000 + " seconds"); return rs; } });
作用
- 方法增强,提高复用
- 简化编程工作,提高效率,可扩展性
- 可以为被代理对象的所有方法做代理
- 支持任意接口类型的实现类做代理