Junit、反射、注解

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 此方法

  1. 能够通过反射技术获取Class字节码对象
    Class c1 = 对象.getClass();
    Class c2 = 类型名.class;
    Class c3 = Class.forName(全名限定的类名);

  2. 能够通过反射技术获取构造方法对象, 并创建对象。
    Class c1 = Class.forName(…);
    Constructor con = c1.getDeclaredConstructor();
    Object obj = con.newInstance();

  3. 能够通过反射获取成员方法对象, 并且调用方法。
    Class c1 = Class.forName(…);
    Object obj = c1.getDeclaredConstructor().newInstance();
    Method m = c1.getDeclaredMethod(“show1”,String.class,int.class);
    m.setAccessible(true);
    m.invoke(obj);
  4. 能够说出注解的作用
    1).注解就是写在源码中的标记,告诉编译器、JVM遇到这种注解应该怎么
    编译/运行程序;
  5. 能够自定义注解和使用注解
    1).自定义注解:
    public @interface MyAnno{
    }
    2).使用注解:
    @MyAnno
    class Demo{
    }
  6. 能够说出常用的元注解及其作用
    1).@Target:此注解应用的位置(类、方法、属性、局部变量…)
    2).@Retention:此注解的”生命周期”(源码,class,运行时)
    例如:
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnno {
    //属性基本格式:数据类型 变量名 () [default 默认值];
    //例如:
    String version();
    String startWith() default “show”;
    }

  7. 能够解析注解并获取注解中的数据
    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);
    }
    }
    }

  8. 能够完成注解的MyTest案例
    参考demo09
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值