网站建设的体会,网站开发的项目开发,创新的宁波网站建设,python基础教程免费下载#x1f3e1;个人主页 #xff1a; 守夜人st #x1f680;系列专栏#xff1a;Java …持续更新中敬请关注… #x1f649;博主简介#xff1a;软件工程专业#xff0c;在校学生#xff0c;写博客是为了总结回顾一些所学知识点 目录单元测试、反射、注解、动态代理单元测… 个人主页 守夜人st 系列专栏Java …持续更新中敬请关注… 博主简介软件工程专业在校学生写博客是为了总结回顾一些所学知识点 目录单元测试、反射、注解、动态代理单元测试单元测试概述单元测试快速入门单元测试常用注解反射反射概述反射获取类对象反射获取成员变量反射获取方法反射的作用——绕过编译阶段为集合添加数据泛型擦除反射的作用——通用框架的底层原理注解注解概述自定义注解元注解注解解析注解的应用场景一JUnit框架动态代理动态代理概述、快速入门动态代理的应用案例做性能分析代理的好处单元测试、反射、注解、动态代理
单元测试
单元测试概述 单元测试就是针对最小的功能单位编写测试代码Java程序最小功能单元是方法因此单元测试就是针对方法的测试进而检查方法的正确性 我们平常采用的测试存在的弊端 只有一个main方法如果一个方法的测试失败了其他反复测试会受到影响 无法得到测试的结果报告需要程序员自己去观察测试是否成功 无法实现自动化测试 JUnit单元测试框架 JUnit是使用Java语言实现的单元测试框架他是开源的Java开发者都应当学习并使用JUnit编写单元测试 此外几乎所有的IDE工具都集成了JUnit这样我们就直接可以在IDE中编写并运行JUnit单元测试 JUnit优点 JUnit可以灵活的选择执行哪些测试方法可以一键执行全部测试方法可以生成全部方法的测试报告单元测试中的某个方法测试失败了不影响其他测试方法的测试 单元测试快速入门 需求使用单元测试进行业务方法预期结果、正确性测试的快速入门 将JUnit的jar包导入到项目中 IDEA通常整合好了JUnit框架一般不需要导入如果IDEA没有整合好需要自己手工导入JUnit的jar包到模块 编写测试方法该方法必须是公共的无参数无返回值的非静态方法在测试方法上使用Test注解标注该方法是一个测试方法在测试方法中完成被测试方法的预期正确性测试选中测试方法选择“ JUnit运行 ”如果测试良好是绿色测试失败是红色 package com.shouyeren.test;public class UserService {public String loginName(String loginName,String passWord){if (admin.equals(loginName) 123456.equals(passWord)){return 登录成功;}else {return 用户名或者密码不正确;}}public void selectNames(){System.out.println(查询所有用户名成功);}
}package com.shouyeren.test;import org.junit.Assert;
import org.junit.Test;public class TestUserService {Testpublic void testLoginName(){UserService userService new UserService();String rs userService.loginName(admin,123456);Assert.assertEquals(您的登录业务功能可能出BUG,登录成功,rs);}Testpublic void testSelectNames(){UserService userService new UserService();userService.selectNames();}
}单元测试常用注解
注解说明JUnit4Test测试方法Before用来修饰实例方法该方法会在每一个测试方法执行之前执行一次After用来修饰实例方法该方法会在每一个测试方法执行之后执行一次BeforeClass用来修饰静态方法该方法会在所有测试方法执行之前执行一次AfterClass用来修饰静态方法该方法会在所有测试方法执行之后执行一次
开始执行的方法初始化资源执行完之后的方法释放资源
反射
反射概述 反射是指对于任何一个Class类在“运行的时候”都可以直接得到这个类的全部成分 构造器对象Constructor 成员变量对象Field 成员方法对象Method 这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制 反射的基本作用、关键
反射是在运行时获取类的字节码文件对象解析获得类中全部成分反射的核心思想和关键就是得到编译后的Class文件
反射获取类对象
获取Class类对象的三种方式
Class c1 Class.forName(“全类名”)Class c2 类名.class;Class c3 对象.getClass();
Class类中用于获取构造器的方法
方法说明Constructor?[ ] getConstructors()返回所有构造器对象的数组只能拿public的Constructor?[ ] getDeclaredConstructors()返回所有构造器对象的数组Constructor?[ ] getConstructor(Class?…parmeterTypes)返回单个构造器对象只能拿public的Constructor?[ ] getDeclaredConstructors(getConstructor(Class?…parmeterTypes)返回单个构造器对象
package com.shouyeren.reflect;import org.junit.Test;import java.lang.reflect.Constructor;public class TestStudent {/*** 获取类中的全部构造器对象public*/Testpublic void getConstructors(){ClassStudent c Student.class;Constructor[] constructors c.getConstructors();for (Constructor constructor : constructors) {System.out.println(constructor.getName() constructor.getParameterCount());}}/*** 获取类中的全部构造器对象*/Testpublic void getDeclaredConstructors(){ClassStudent c Student.class;Constructor[] constructors c.getDeclaredConstructors();for (Constructor constructor : constructors) {System.out.println(constructor.getName() constructor.getParameterCount());}}/*** 获取某个构造器对象public*/Testpublic void getConstructor() throws NoSuchMethodException {ClassStudent c Student.class;//可以添加参数Constructor cons c.getConstructor(String.class,int.class);System.out.println(cons.getName() cons.getParameterCount());}/*** 获取某个构造器对象*/Testpublic void getDeclaredConstructor() throws NoSuchMethodException {ClassStudent c Student.class;//可以添加参数类型Constructor cons c.getDeclaredConstructor();System.out.println(cons.getName() cons.getParameterCount());Constructor cons1 c.getDeclaredConstructor(String.class,int.class);System.out.println(cons.getName() cons1.getParameterCount());}
}
package com.shouyeren.reflect;public class Student {private String name;private int age;private Student() {}public Student(String name, int age) {this.name name;this.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;}
}
使用反射技术获取构造器对象并使用
获取构造器的作用依然是初始化一个对象返回
符号说明T newInstance(Object… initargs)根据指定的构造器创建对象public void setAccessible(boolean flag)设置为true表示取消访问检查进行暴力反射
package com.shouyeren.reflect;import org.junit.Test;import java.lang.reflect.Constructor;public class TestStudent1 {Testpublic void getDeclaredConstructor() throws Exception {ClassStudent c Student.class;//可以添加参数类型Constructor cons c.getDeclaredConstructor();System.out.println(cons.getName() cons.getParameterCount());//私有构造器无法访问时可以暴力反射cons.setAccessible(true);Student s (Student) cons.newInstance();System.out.println(s);Constructor cons1 c.getDeclaredConstructor(String.class,int.class);System.out.println(cons.getName() cons1.getParameterCount());Student s1 (Student) cons1.newInstance(叶文洁, 58);System.out.println(s1.getName() s1.getAge());}
}反射获取成员变量
使用反射技术获取成员变量对象并使用
反射的第一步是先得到类对象然后从类对象中获取类的成分对象Class类中用于获取成员变量的方法
方法说明Field[] getFields()返回所有成员变量对象的数组(public)Field[] getDeclaredFields()返回所有成员变量对象的数组Field[] getField(String name)返回单个成员变量对象(public)Field[] getDeclaredField(String name)返回单个成员变量对象
package com.shouyeren.reflect;import org.junit.Test;import java.lang.reflect.Field;
/*** | Field[] getFields() | 返回所有成员变量对象的数组(**public**) |* | Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |* | Field[] getField(String name) | 返回单个成员变量对象(**public**) |* | Field[] getDeclaredField(String name) | 返回单个成员变量对象 |*/
public class FieldDemo {/*** Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |*/Testpublic void getDeclaredFields(){//定位Class对象ClassStudent s Student.class;//定位所有成员变量对象Field[] fields s.getDeclaredFields();for (Field field : fields) {System.out.println(field.getName() field.getType());}}/*** Field[] getFields() | 返回所有成员变量对象的数组(**public**) |*/Testpublic void getFields(){//定位Class对象ClassStudent s Student.class;//定位所有成员变量对象Field[] fields s.getFields();for (Field field : fields) {System.out.println(field.getName() field.getType());}}/*** Field[] getField(String name) | 返回单个成员变量对象(**public**)* throws Exception*/Testpublic void getField() throws Exception {//定位Class对象ClassStudent s Student.class;//成员变量对象Field field s.getField(schoolName);System.out.println(field.getName() field.getType());}/*** Field[] getDeclaredField(String name) | 返回单个成员变量对象 |* throws Exception*/Testpublic void getDeclaredField() throws Exception {//定位Class对象ClassStudent s Student.class;//成员变量对象Field field s.getDeclaredField(age); //打开权限field.setAccessible(true);Student student new Student(张三,20);//赋值field.set(student,18);//取值System.out.println(field.get(student));}}反射获取方法
使用反射技术获取方法对象并使用
反射的第一步是先得到类对象然后从类对象中获取类的成分对象Class类中用于获取成员方法的方法
方法说明Method[ ] getMethods()返回所有成员方法对象的数组(public)Method[ ] getDeclaredMethods()返回所有成员方法对象的数组Method[ ] getMethod()返回单个成员方法对象的数组(public)Method[ ] getDeclaredMethod()返回单个指定成员方法对象的数组
反射的作用——绕过编译阶段为集合添加数据泛型擦除 反射是作用在运行时的技术此时集合的泛型将不能产生约束了此时是可以为集合存入其他任意类型的元素的 ArrayListInteger list new ArrayList();
list.add(100);
list.add(字符串);//报错泛型只是在编译阶段可以约束集合只能操作某种数据类型在编译成Class文件进入运行阶段的时候其真实类型都是ArrayList泛型相当于被擦除了
package com.shouyeren.reflect;import java.lang.reflect.Method;
import java.util.ArrayList;public class ReflectDemo {public static void main(String[] args) throws Exception {ArrayListInteger list1 new ArrayList();ArrayListInteger list2 new ArrayList();System.out.println(list1.getClass() list2.getClass());System.out.println(--------------------------------------);ArrayListInteger list3 new ArrayList();list3.add(18);list3.add(20);//list3.add(字符串);Class c list3.getClass();Method add c.getDeclaredMethod(add, Object.class);boolean rs (boolean) add.invoke(list3,字符串);System.out.println(list3);System.out.println(rs);}
} 反射的作用——通用框架的底层原理 需求给你任意一个对象在不清楚对象字段的情况下可以把对象的字段名称和对应值存储到文件中去 定义一个方法可以接收任意类对象每次收到一个对象后需要解析这个对象的全部成员变量名称。这个对象可能是任意的那么怎么样才可以知道这个对象的全部成员变量名称呢使用反射获取对象的Class文件然后获取全部成员变量信息遍历全部成员变量信息然后提取本成员变量在对象中的具体值存入成员变量名称和值到文件中 package com.shouyeren.reflect.framework;import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;public class MybatisUtil {/*** 保存任意类型的对象* param obj*/public static void save(Object obj){try(PrintStream ps new PrintStream(new FileOutputStream(src/data.txt,true))) {//获取这个对象的全部成员变量Class c obj.getClass();ps.println(---------------- c.getSimpleName() ----------------);Field[] fields c.getDeclaredFields();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();}}
}package com.shouyeren.reflect.framework;/*** 提供一个通用框架支持保存所有对象的具体信息*/
public class ReflectDemo {public static void main(String[] args) {Student student new Student();student.setName(张三);student.setClassName(实验一班);student.setAge(20);student.setHobby(打球);student.setSex(男);MybatisUtil.save(student);Teacher teacher new Teacher();teacher.setName(苍老师);teacher.setSex(女);teacher.setSalary(12000);MybatisUtil.save(teacher);}
}反射的作用
可以在运行阶段得到一个类的全部成分然后操作可以破坏封装性可以破坏泛型约束更重要的用途是适合做Java高级框架
注解
注解概述 Java注解(Annotation)又称Java标注是JDK5.0引入的一种注释机制 Java语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注 例如JUnit框架中标记了注解Test的方法就可以被当成测试方法执行 自定义注解
自定义注解格式
public interface 注解名称{public 属性类型 属性名() default 默认值;
}特殊属性
value属性如果只有一个value属性的情况下使用value属性的时候可以省略value名称不写但是如果有多个属性且多个属性没有默认值那么value名称是不能省略的
元注解 元注解就是注解的注解 元注解有两个 Target约束自定义注解只能在哪些地方使用Retention声明注解的生命周期 Target
TYPE类接口FIELD成员变量METHOD成员方法PARAMETER方法参数CONSTRUCTOR构造器LOCAL_VARIABLE局部变量
Retention中可使用的值定义在RetentionPolicy枚举类中常用值如下
SOURCE注解只作用在源码阶段生成的字节码文件中不存在CLASS注解作用在源码阶段字节码文件阶段运行阶段不存在默认值RUNTIME注释在源码阶段、字节码文件阶段运行阶段开发常用
注解解析 注解的操作中经常需要进行解析注解的解析就是判断是否存在注解存在注解就解析出内容 与注解解析相关的接口 Annotation注解的顶级接口注解都是Annotation类型的对象AnnotatedElement该接口定义了与注解解析相关的解析方法 注解解析的技巧
注解在哪个成分上就先拿哪个成分对象比如注解作用成员方法则要获得该成员方法对应的Method对象再拿上面的注解
注解的应用场景一JUnit框架
模拟JUnit框架 定义若干个方法只要加了MyTest注解就可以在启动时被触发执行 分析 定义一个自定义注解MyTest只能注解方法存活范围是一直在定义若干个方法只要有MyTest注解的方法就能在启动时被触发执行没有该注解则不能执行 package com.shouyeren.annotation;import java.lang.annotation.*;Target({ElementType.METHOD,ElementType.FIELD})
Retention(RetentionPolicy.RUNTIME)
public interface MyTest {}package com.shouyeren.annotation;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class AnnotationTest {MyTestpublic void test1(){System.out.println(test1);}public void test2(){System.out.println(test2);}MyTestpublic void test3(){System.out.println(test3);}public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {AnnotationTest test new AnnotationTest();Class c AnnotationTest.class;Method[] methods c.getDeclaredMethods();for (Method method : methods) {if (method.isAnnotationPresent(MyTest.class)){method.invoke(test);}}}
}动态代理
动态代理概述、快速入门
如何创建代理对象
Java中代理的代表类是java.lang.reflect.ProxyProxy提供了一个静态方法用于为对象产生一个代理对象返回
动态代理的应用案例做性能分析代理的好处 需求 模拟某企业用户管理业务需包含用户登录用户删除用户查询功能并统计每个功能的耗时 分析 定义一个UserService表示用户业务接口规定必须完成用户登录用户删除用户查询功能定义一个UserServiceImpl实现UserService并完成相关功能且统计每个功能的耗时定义测试类创建实现类对象调用方法 package com.shouyeren.proxy;public interface UserService {String login(String loginName,String passWord);void deleteUsers();String selectUsers();
}package com.shouyeren.proxy;public class UserServiceImpl implements UserService{Overridepublic String login(String loginName, String passWord) {String rs 登录名和密码错误;if (admin.equals(loginName) 132456.equals(passWord)){rs 登录成功;}try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}return rs;}Overridepublic void deleteUsers() {System.out.println(正在删除用户数据。。。);try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}}Overridepublic String selectUsers() {String rs 正在查询10000个用户数据。。。;try {Thread.sleep(2500);} catch (Exception e) {e.printStackTrace();}return rs;}
}package com.shouyeren.proxy;import java.lang.reflect.Proxy;public class ProxyUtil {public static UserService getProxy(UserService obj){return (UserService) Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(), (proxy, method, args) - {long startTime System.currentTimeMillis();Object rs method.invoke(obj, args);long endTime System.currentTimeMillis();System.out.println(method.getName() 方法耗时 (endTime-startTime)/1000 S);return rs;});}
}package com.shouyeren.proxy;public class Test {public static void main(String[] args) {UserService userService ProxyUtil.getProxy(new UserServiceImpl());System.out.println(userService.login(admin, 132456));System.out.println(userService.selectUsers());userService.deleteUsers();}
}动态代理的优点
可以在不改变方法源码的情况下实现对方法功能的增加提高了代码的复用。简化了编程 工作、提高了开发效率、同时提高了软件系统的可扩展性可以为被代理对象的所有方法做代理 非常的灵活支持任意接口类型的实现类对象做代理也可以直接为接口本身做代理
感觉不错的话动手点个赞吧