01.第一章:JUnit单元测试_JUnit概述:
1).什么是"JUnit":它是一个第三方的类库。并打包为一个xxx.jar文件。这是一个“压缩文件”,这个jar包就可以复制到我们项目目录下,供我们项目使用。
2).JUnit的作用:它内部提供了一些写好的“注解”,这些注解可以方便的让我们进行“单元测试”
例如:
main(){
//列出菜单
//调用方法
}
public static void 方法(){
//调用方法
}
public static void 方法2(){
//调用方法
}
public static void calc(){
//此方法如果写完,每次测试都需要从main()开始,
//这样就会很麻烦
//如果想单独测试这个方法,这时可以使用JUnit进行“单元测试”
}
3).一些主流集成开发环境都提供了JUnit的支持,内部自动包含JUnit的工具,
我们可以直接使用。
02.第一章:JUnit单元测试JUnit的使用@Test注解:
1).项目中第一次使用JUnit的时候:
2).步骤:
1).在某个方法上写一个@Test注解:
2).此时注解为红色,光标落到注解位置,alt + 回车
3).回车
4).在有注解的方法上右键-->Run "show()"
3).其它说明:
1).在一个方法中,可以包含多个@Test方法。可以同时运行,也可以单独运行;
2).在类名上右键-->Run "xxx类名":可以运行所有的@Test方法,运行顺序是根据“方法名”的自然排序。在某个"@Test"方法上右键-->Run "xxx方法":可以单独运行。
3).@Test的方法必须是:**public**
@Test方法不能是static的方法
@Test方法必须是**无参,无返回值**;
03.第一章:JUnit单元测试_其它注解:
1).@Before:被修饰的方法会在@Test方法之前运行。多个@Before方法会依次按方法名降序并调用。
2).@After:被修饰的方法会在@Test方法之后运行。多个@After方法会依次按方法名升序调用。
3).@BeforeClass : 用在静态方法上,而且不论多少个@Test,此方法只执行一次
4).@AfterClass : 用在静态方法上,而且不论多少个@Test,此方法只在@Test之后执行一次。
示例代码:
public class Demo {
@Test
public void show1(){
System.out.println("show1...");
}
@Test
public void show2(){
System.out.println("show2");
}
@Before
public void b1(){
System.out.println("b1...");
}
@Before
public void b2(){
System.out.println("b2...");
}
@BeforeClass
public static void b3(){
System.out.println("静态的b3...");
}
@After
public void a1(){
System.out.println("a1...");
}
@After
public void a2(){
System.out.println("a2...");
}
@AfterClass
public static void a3(){
System.out.println("静态的a3....");
}
}
05.第二章:反射_反射的概念及演示:
1).案例演示:
见demo03
2).反射的概念:在程序运行时,可以通过“字符串”的类名去获取这个class文件并创建这个类对象,并且可以获取这个类内部的信息:构造方法、成员属性、成员方法,进而可以调用这些成员,包括私有的。
06.第二章:反射_运行时class文件的加载:
JVM在运行时,会为每个类在方法区中创建一个Class对象,而且针对一个类,只创建一个Class对象。这个Class中存储了这个类的内部信息,可以通过这个Class类对象,去间接的操作那个类。
07.第二章:反射_获取Class对象的三种方式:
public static void main(String[] args) throws ClassNotFoundException {
//1.Object -> getClass()
Student stu = new Student();
Class c1 = stu.getClass();
//2.任何数据类型都有一个静态属性:class
Class c2 = Student.class;
System.out.println(c1 == c2);
//3.使用Class类的静态方法:forName(全名限定的类名)
Class c3 = Class.forName("cn.itheima.demo05_获取class的三种方式.Student");
System.out.println(c1 == c3);
}
08.第二章:反射_获取构造方法并创建对象:
1).获取构造方法的常用方法:
1).public Constructor[] getConstructors():获取所有公有构造方法。
2).public Constructor[] getDeclaredConstructors():获取任意修饰符的所有构造方法。
3).public Constructor getDeclaredConstructor(Class ... params):获取某个参数的构造方法
2).示例代码:
public static void main(String[] args) throws Exception {
//1.获取它的Class对象
Class c = Class.forName("cn.itheima.demo06_获取构造方法并创建对象.Student");
//2.获取公有无参构造方法
Constructor c1 = c.getDeclaredConstructor();
Object obj = c1.newInstance();
//3.获取私有int参数的构造方法
Constructor c2 = c.getDeclaredConstructor(int.class);
c2.setAccessible(true);//暴力访问
Object obj2 = c2.newInstance(10);
}
09.第二章:反射_获取成员属性并赋值和取值:
1).获取成员属性的常用方法:
1).public Field[] getFields():获取所有公有成员属性。
2).public Field[] getDeclaredFields():获取任意修饰符的所有成员属性。
3).public Field getDeclaredField(String fieldName):获取某个成员属性
2).示例代码:
public static void main(String[] args) throws Exception {
//1.获取它的Class对象
Class c = Class.forName("cn.itheima.demo07_获取成员属性并调用.Student");
Student stu1 = (Student)c.getDeclaredConstructor().newInstance();
Student stu2 = (Student)c.getDeclaredConstructor().newInstance();
//2.获取它的公有成员属性:
Field f = c.getDeclaredField("name");
//第一个对象的name赋值:刘德华
f.set(stu1, "刘德华");
//第二个对象的name属性赋值:张学友
f.set(stu2,"张学友");
//3.获取私有成员属性
f = c.getDeclaredField("age");
f.setAccessible(true);
f.set(stu1, 18);
f.set(stu2, 20);
System.out.println(stu1);
System.out.println(stu2);
}
10.第二章:反射_获取成员方法并调用:
1).获取成员方法的常用方法:
1).public Method[] getMethods():获取所有公有成员方法。
2).public Method[] getDeclaredMethods():获取任意修饰符的所有成员方法。
3).public Method getDeclaredMethod(String methodName,Class ... params):获取某个成员方法
2).示例代码:
public static void main(String[] args) throws Exception {
//1.获取Class
Class c = Class.forName("cn.itheima.demo08_获取成员方法并调用.Student");
//2.获取公有成员方法
Method m = c.getDeclaredMethod("show2");
//3.创建对象
Object obj = c.getDeclaredConstructor().newInstance();
//4.调用方法
m.invoke(obj);
//5.获取私有的show1()方法
m = c.getDeclaredMethod("show1", String.class, int.class);
m.setAccessible(true);
Object result = m.invoke(obj, "张三", 18);
System.out.println("返回值:" + result);
}
11.第三章:注解_注解的概念及作用:
1).“注解”:编写在“源码中”,作为一个“标记”,给编译器,或者JVM看的。
2).编译器或者JVM看到注解后,就可以了解期望下面的代码是做什么的,然后按照这个要求去编译/运行这段代码;
例如:
1).给编译器看的注解:
class Fu{
public void eat(){
}
}
class Zi extends Fu{
@Override
public void eat(String s){//编译错误
}
}
2).给JVM运行时看的:@Test
class Demo{//此处右键-->Run Demo-->所有的@Test的方法都会被执行
@Test//执行
public void show1(){
}
@Test//执行
public void show2(){
}
public void show3(){
}
}
12.第三章:注解_JDK内部注解:
1).@Override : 用在子类重写父类方法时,给编译器看的,用于检查重写的语法;
2).@FunctionalInterface : 用在函数接口上,给编译器看的,用于检查函数式接口的语法。
13.第三章:注解_自定义注解的基本格式:
class Student{
@自定义注解
private String name;
}
定义注解的语法:
public @interface MyAnno {
}
14.第三章:注解_元注解:
1).元注解的作用:元注解本质上也是注解,它是对注解进行注解的注解;就是在定义注解时使用的注解。它可以规范我们定义的注解可以使用在什么位置上、以及出现的位置(源码、class、运行时)
2).两种元注解:
1).@Targe:定义注解可以使用的位置;
例如:
@Targe(ElementType.TYPE):可以在类上,接口上使用:
@Targe(ElementType.FIELD):可以在属性上使用:
@Targe(ElementType.METHOD):可以在方法上使用:
@Targe(ElementType.CONSTRUCTOR):可以在构造方法上使用:
@Targe(ElementType.LOCAL_VARIABLE):可以在局部变量上使用:
@Targe(ElementType.PARAMETER):可以在形参上使用:
2).Retention:定义注解可以出现的位置:
例如:
@Retention(RetentionPolicy.SOURCE):只能出现的源码中;
@Retention(RetentionPolicy.CLASS):可以出现在源码和class文件中;
@Retention(RetentionPolicy.RUNTIME):可以出现源码、class、运行时(给JVM看的)
3).示例代码:
@Target({ElementType.METHOD})//表示:MyAnno注解只能用在方法上
@Retention(RetentionPolicy.RUNTIME)//表示:出现在运行时给JVM看的
public @interface MyAnno {
}
15.第三章:注解_解析注解:
1).注解解析器也是基于反射的;
2).代码实现:
1).自定义注解:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
}
2).使用注解:
public class Demo {
private int age;
@MyAnno
public void show2(){
System.out.println("show2....");
}
@MyAnno
public void show1(){
System.out.println("show1...");
}
@Test
public void show3(){
System.out.println("show3....");
}
//模拟注解解析器:
public static void main(String[] args) throws Exception {
//1.获取使用了注解的类的Class对象
Class c = Demo.class;
Object obj = c.getDeclaredConstructor().newInstance();
//2.获取所有的方法
Method[] methodArray = c.getDeclaredMethods();
//3.遍历每个Method对象
for (Method m : methodArray) {
//4.判断这个方法上是否使用了MyAnno注解
if (m.isAnnotationPresent(MyAnno.class)) {
//5.是:执行这个m方法
m.invoke(obj);
}
}
}
}
16.第三章:注解_自定义带属性的注解:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
//属性基本格式:数据类型 变量名 () [default 默认值];
//例如:
String version();
String startWith() default "show";
}
public class Demo {
private int age;
@MyAnno(version = "1.0",startWith = "test")
public void test2(){
System.out.println("show2....");
}
@MyAnno(version = "2.0")
public void show1(){
System.out.println("show1...");
}
@Test
public void show3(){
System.out.println("show3....");
}
//模拟注解解析器:
public static void main(String[] args) throws Exception {
//1.获取使用了注解的类的Class对象
Class c = Demo.class;
Object obj = c.getDeclaredConstructor().newInstance();
//2.获取所有的方法
Method[] methodArray = c.getDeclaredMethods();
//3.遍历每个Method对象
for (Method m : methodArray) {
//4.判断这个方法上是否使用了MyAnno注解
if (m.isAnnotationPresent(MyAnno.class)) {
//获取注解对象
MyAnno myAnno = m.getAnnotation(MyAnno.class);
//获取注解的属性值
String value = myAnno.version();
System.out.println("版本号:" + value);
value = myAnno.startWith();
System.out.println("方法应该以:" + value + " 开头");
//获取方法名,验证是否以value开头
String methodName = m.getName();
if (!methodName.startsWith(value)) {
System.out.println("你的方法没有以:" + value + " 开头,这次我原谅你!");
}
//5.是:执行这个m方法
m.invoke(obj);
}
}
}
}
学习目标:
1 . 能够使用Junit进行单元测试
在要测试的方法上添加注释:@Test –》右键 -》Run 此方法
能够通过反射技术获取Class字节码对象
Class c1 = 对象.getClass();
Class c2 = 类型名.class;
Class c3 = Class.forName(全名限定的类名);能够通过反射技术获取构造方法对象, 并创建对象。
Class c1 = Class.forName(…);
Constructor con = c1.getDeclaredConstructor();
Object obj = con.newInstance();
…- 能够通过反射获取成员方法对象, 并且调用方法。
Class c1 = Class.forName(…);
Object obj = c1.getDeclaredConstructor().newInstance();
Method m = c1.getDeclaredMethod(“show1”,String.class,int.class);
m.setAccessible(true);
m.invoke(obj); - 能够说出注解的作用
1).注解就是写在源码中的标记,告诉编译器、JVM遇到这种注解应该怎么
编译/运行程序; - 能够自定义注解和使用注解
1).自定义注解:
public @interface MyAnno{
}
2).使用注解:
@MyAnno
class Demo{
} 能够说出常用的元注解及其作用
1).@Target:此注解应用的位置(类、方法、属性、局部变量…)
2).@Retention:此注解的”生命周期”(源码,class,运行时)
例如:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
//属性基本格式:数据类型 变量名 () [default 默认值];
//例如:
String version();
String startWith() default “show”;
}能够解析注解并获取注解中的数据
public class Demo {private int age;
@MyAnno(version = “1.0”,startWith = “test”)
public void test2(){
System.out.println(“show2….”);
}
@MyAnno(version = “2.0”)
public void show1(){
System.out.println(“show1…”);
}
@Test
public void show3(){
System.out.println(“show3….”);
}
}
main(){
//1.获取使用了注解的那个类的Class
Class c = Class.forName(“..Demo”);
//2.创建对象
Object obj = c.getDeclaredConstructor().newInstance();
//3.获取所有方法
Method[] methodArray = c.getDeclaredMethods();
//4.遍历
for(Method m : methodArray){
//判断此方法是否使用了MyAnno注解
if(m.isAnnotationPresent(MyAnno.class)){
//获取注解的属性值
//1.获取注解对象
MyAnno anno = m.getAnnotation(MyAnno.class);
//2.获取version属性的值
String v = anno.version();
System.out.println(v);
….
//3.执行此方法
m.invoke(obj);
}
}
}- 能够完成注解的MyTest案例
参考demo09