Java单元测试、反射、注解

单元测试

Junit

public class UserService {
    public String login(String loginName, String password) {
        if ("admin".equals(loginName) && "123456".equals(password)) {
            return "success";
        }
        return "用户名或密码错误";
    }
}


public class UserServiceTest {
    /**
     * 测试方法要求:
     * 1.必须public修饰
     * 2.没有返回值没有参数
     * 3.必须使注解@Test修饰
     */
    @Test
    public void testLogin() {
        UserService userService = new UserService();
        String rs = userService.login("admin", "123456");
        // 断言预期结果的正确性
        /**
         * 参数一:测试失败的提示信息
         * 参数二:期望值
         * 参数三:实际值
         */
        Assert.assertEquals("登录业务功能方法有误", "success", rs);
    }
}

 

Junit常用注解

 

如Junit4,如5个注解都有,则执行顺序为@BeforeClass、@Before、@Test、@After、@AfterClass

 

反射

 

反射获取类对象

public class ReflectDemo01 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 反射的第一步永远是先得到类的Class文件对象:字节码文件
        // 1.类名.class
        Class c1 = Student.class;
        System.out.println(c1);
    
        // 2.对象.getClass()
        Student swk = new Student();
        Class c2 = swk.getClass();
        System.out.println(c2);

        // 3.Class.forName("类的全限名")
        Class c3 = Class.forName("Student");
        System.out.println(c3);
    }
}

 

反射获取构造器对象

public class ReflectDemo01 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 反射的第一步永远是先得到类的Class文件对象:字节码文件
        // 1.类名.class
        Class c1 = Student.class;
        System.out.println(c1);

        // 2.对象.getClass()
        Student swk = new Student();
        Class c2 = swk.getClass();
        System.out.println(c2);

        // 3.Class.forName("类的全限名")
        Class c3 = Class.forName("Student");
        System.out.println(c3);
    }

    @Test
    public void getConstructors() {
        // 1.反射第一步得到Class类对象
        Class c = Student.class;

        // 2.定位全部构造器,只能拿public修饰
        Constructor[] cons = c.getConstructors();

        // 3.遍历构造器
        for (Constructor con: cons) {
            System.out.println(con.getName() + "===>" + con.getParameterCount());
        }
    }

    @Test
    public void getDeclaredConstructors() {
        // 1.反射第一步得到Class类对象
        Class c = Student.class;

        // 2.定位全部构造器,只要申明了就可以拿到
        Constructor[] cons = c.getDeclaredConstructors();

        // 3.遍历构造器
        for (Constructor con: cons) {
            System.out.println(con.getName() + "===>" + con.getParameterCount());
        }
    }

    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException {
        // 1.反射第一步得到Class类对象
        Class c = Student.class;

        // 2.定位全部构造器,只要申明了就可以拿到
        // Constructor con = c.getDeclaredConstructor();
        Constructor con = c.getDeclaredConstructor(String.class, int.class);
        // 3.遍历构造器
        System.out.println(con.getName() + "===>" + con.getParameterCount());
    }
}

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    private 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;
    }
}

 

反射获取构造器然后通过构造器初始化对象

 

    // 调用无参构造器得到一个类的对象返回
    @Test
    public void createObj01() throws Exception {
        // a.反射第一步是先得到Class类对象
        Class c = Student.class;
        // b.定位无参数构造器对象
        Constructor constructor = c.getDeclaredConstructor();
        // c.通过无参数构造器初始化对象返回
        constructor.setAccessible(true);
        // d.通过无参数构造器初始化对象返回
        Student swk = (Student) constructor.newInstance();
        System.out.println(swk);
    }

    // 调用有参构造器得到一个类的对象返回
    @Test
    public void createObj02() throws Exception {
        // a.反射第一步是先得到Class类对象
        Class c = Student.class;
        // b.定位无参数构造器对象
        Constructor constructor = c.getDeclaredConstructor(String.class, int.class);

        // c.通过有参数构造器初始化对象返回
        Student swk = (Student) constructor.newInstance("测试", 100);
        System.out.println(swk);
    }

 

反射获取Field成员变量对象及赋值

    /**
     * 获取全部的成员变量
     * @throws Exception
     */
    @Test
    public void createObj03() throws Exception {
        // a.反射第一步是先得到Class类对象
        Class c = Dog.class;
        // b.获取全部申明的成员变量对象
        Field[] fields = c.getDeclaredFields();
        for (Field field: fields) {
            System.out.println(field.getName()+"");
        }

        Field nameF = c.getDeclaredField("name");

        // c. 为这个成员变量赋值
        Dog taidi = new Dog();
        /**
         * 参数一:被赋值的对象
         * 参数二:该成员变量的值
         */
        nameF.setAccessible(true);
        nameF.set(taidi, "勇敢的泰迪");
        System.out.println(taidi);

        String value = nameF.get(taidi) + "";
        System.out.println(value);
    }

 

反射获取Method方法对象

    /**
     * 获取所有方法对象
     */
    @Test
    public void getDeclaredMethods() {
        Class d = Dog.class;

        Method[] methods = d.getDeclaredMethods();

        for (Method method: methods) {
            System.out.println(method.getName() + "====>" + method.getParameterCount() + "===>" + method.getReturnType());

        }
    }

    /**
     * 获取某个方法对象
     */
    @Test
    public void getDeclardMethod() throws Exception {
        // 1.先获取class类对象
        Class c = Dog.class;
        // 2.定位它的某个方法
        Method run = c.getDeclaredMethod("run");
        // 3.触发方法执行
        Dog jinmao = new Dog();
        run.invoke(jinmao); // 触发jinMao对象的run()方法执行

        /**
         * 参数一:方法名称
         * 参数二:方法的参数个数和类型(可变参数)
         */
        Method eat = c.getDeclaredMethod("eat", String.class);
        eat.setAccessible(true);
        /**
         * 参数一:被触发方法所在的对象
         * 参数二:方法需要的入参值
         */
        eat.invoke(jinmao, "肉");
        System.out.println();
    }

public class Dog {
    private void eat() {
        System.out.println("狗吃骨头");
    }

    private void eat(String name) {
        System.out.println("狗吃" + name);
    }

    public void run() {
        System.out.println("狗在跑");
    }
}

 

反射破坏类的封装性与泛型的约束性

    @Test
    public void getDeclardMethod1() throws Exception {
        // 泛型只能工作在编译阶段,运行阶段泛型就消失了
        // 反射工作在运行阶段
        List<Double> scores = new ArrayList<>();
        scores.add(24.1);
        scores.add(123.4);

        // 拓展:通过反射暴力注入一个其它类型数据
        Class c = scores.getClass();
        // 从ArrayList的class对象中定位add方法
        Method add = c.getDeclaredMethod("add", Object.class);
        // 出发scores集合对象中的add执行(运行阶段,泛型不能约束了)
        add.invoke(scores, "波仔");
        System.out.println(scores);
    }

 

反射的作用

    public static void main(String[] args) throws ClassNotFoundException {
        Dog dog = new Dog("haha", 15, "红");
        MyBatis.save(dog);
    }

public class Dog {
    private String name;
    private int age;
    private String color;

    public Dog(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public Dog() {
    }

    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;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}


import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

public class MyBatis {
    // 提供一个方法:可以保存一切对象数据的字段和具体值
    public static void save(Object obj) {
        try (
                PrintStream ps = new PrintStream(new FileOutputStream("反射/src/test.txt", true));
        ) {
            // 1.先得到对象的Class文件对象
            Class c = obj.getClass();
            // 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();
        }
    }
}

 

 

注解

 

自定义注解

 

注解的属性

 

注解的特殊属性

 

元注解——是用在自定义注解上的注解

 

 

 

 

 

 注解的解析

 

 

@Book(value="test1", authors = {"1", "2"}, price = 5.1)
public class MyBook {
    public static void main(String[] args) throws NoSuchMethodException {
        // 1.定位Class类对象
        Class c = BookStore.class;
        // 2.判断这个类上是否使用了某个注解
        if (c.isAnnotationPresent(Book.class)) {
            // 3.获取这个注解对象
            Book book = (Book) c.getDeclaredAnnotation(Book.class);
            System.out.println(book.value());
            System.out.println(book.price());
        }

        Method run = c.getDeclaredMethod("run");

        // 2.判断这个方法上是否使用了某个注解
        if (run.isAnnotationPresent(Book.class)) {
            // 3.获取这个注解对象
            Book book = (Book) run.getDeclaredAnnotation(Book.class);
            System.out.println(book.value());
            System.out.println(book.price());
        }
    }
}

@Book(value = "Java基础精通", price = 50, authors = {"脖子", "哈哈"})
class BookStore {
    @Book(value = "Java基础精通1", price = 500, authors = {"脖1子", "哈2哈"})
    public void run() {

    }
}
// 自定义一个注解
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE}) // 申明只能注解方法与成员变量与类
    @Retention(RetentionPolicy.RUNTIME)
@interface Book {
    String value();
    String[] authors();
    double price();
    String address() default "广州";
}

 

注解模拟Junit框架的基本使用

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyTest {

}

MyBook t = new MyBook();
Class d = MyBook.class;
// 2.获取类中全部方法对象
Method[] methods = d.getDeclaredMethods();
for (Method method: methods) {
  if (method.isAnnotationPresent(MyTest.class)) {
    // 触发此方法执行
    method.invoke(t);
    }
} @MyTest
public void test01() {   System.out.println("====test01===="); } @MyTest public void test02() {   System.out.println("====test02===="); } @MyTest public void test03() {   System.out.println("====test03===="); }

  

 

posted @ 2022-04-18 00:47  天叔  阅读(203)  评论(0编辑  收藏  举报