面向对象进阶12

一、单元测试

1.单元测试概述

(1)单元测试

  • 针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此,单元测试就是针对Java方法的测试,进而检查方法的正确性

(2)Junit单元测试框架

  • JUnit是使用Java语言实现的单元测试框架,是开源的
  • 所有的IDE工具都集成了JUnit

(3)JUnit优点

  • 灵活选择执行哪些测试方法,可一键执行全部测试方法;
  • Junit可生成全部方法的测试报告;
  • 单元测试中的某个方法测试失败了,不会影响其他测试方法的测试。
2.单元测试入门
  1. 将JUnit的jar包导入项目
  2. 编写测试方法:该测试方法必须是公共的无参数无返回值的非静态方法
  3. 在测试方法上使用@Test注解,标注该方法是一个测试方法
  4. 在测试方法中完成被测试方法的预期正确性测试
  5. 选中测试方法,选择“JUnit”运行。
3.单元测试常用注解

在这里插入图片描述

二、反射

1.反射概述

(1)反射概述

  • 反射是指对于任何一个Class类,在“运行的时候”都可以直接得到这个类全部成分;
  • 在运行时,可以直接得到这个类的构造器对象:Constructor
  • 在运行时,可以直接得到这个类的成员变量对象:Field
  • 在运行时,可以直接得到这个类的成员方法对象:Method
  • 这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制

(2)反射的关键

  • 反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分
    在这里插入图片描述
2.反射获取类对象

反射的第一步:获取Class类的对象

public class Test {
    public static void main(String[] args) throws Exception {
        Class c = Class.forName("d1_reflect_class.Student");
        System.out.println(c);

        //2.类名.class
        Class c1 = Student.class;
        System.out.println(c1);

        //3. 对象.getClass()获取对象对应类的Class对象
        Student s = new Student();
        Class c2 = s.getClass();
        System.out.println(c2);
    }
}
3.反射获取构造器对象
  • 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
    //1.getConstructors:
    //获取全部的构造器:只能获取public修饰的构造器
    //Constructor[] getConstructors
    @Test
    public void getConstructors(){  //只能拿public修饰的构造器
        //o1.获取类对象
        Class c = Student.class;
        //o2.提取类中的全部构造器对象
        Constructor[] constructors = c.getConstructors();
        //o3. 遍历构造器看有没有拿到
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName()+"1===>"+constructor.getParameterCount());
        }
    }

    //2.getDeclaredConstructors():
    //获取全部的构造器,只要你敢写,这里就能拿到,无所谓权限是否可及
    @Test
    public void getDeclaredConstructors(){
        //o1.获取类对象
        Class c = Student.class;
        //o2.提取类中的全部构造器对象
        Constructor[] constructors = c.getDeclaredConstructors();
        //o3. 遍历构造器看有没有拿到
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName()+"2===>"+constructor.getParameterCount());
        }
    }

    //3.getConstructor(Class...parameterTypes)
    //获取某个构造器,只能拿public修饰的某个构造器
    @Test
    public void getConstructor() throws Exception{
        Class c = Student.class;
        //o2.定位单个构造器对象
        Constructor cons = c.getConstructor();
        System.out.println(cons.getName()+"3===>"+cons.getParameterCount());
    }

    //4.getDeclaredConstructor
    //获取某个构造器,只要你敢写,这里就能拿到,无所谓权限是否可及
    @Test
    public void getDeclaredConstructor() throws Exception{
        //o1.获取类对象
        Class c = Student.class;
        //o2.提取类中的单个构造器对象
        Constructor con = c.getDeclaredConstructor();
        System.out.println(con.getName()+"4===>"+con.getParameterCount());

        //定位某个有参构造器
        Constructor con2 = c.getDeclaredConstructor(String.class,int.class);
        System.out.println(con2.getName()+"5===>"+con2.getParameterCount());
    }
  • 获取构造器的作用依旧是初始化一个对象返回
  @Test
    public void getDeclaredConstructor() throws Exception{
        //o1.获取类对象
        Class c = Student.class;
        //o2.提取类中的单个构造器对象
        Constructor con = c.getDeclaredConstructor();
        System.out.println(con.getName()+"4===>"+con.getParameterCount());

        //如果遇到私有的构造器,可以暴力反射
        con.setAccessible(true);  //权限被打开

        Student s = (Student) con.newInstance();
        System.out.println(s);

        //定位某个有参构造器
        Constructor con2 = c.getDeclaredConstructor(String.class,int.class);
        System.out.println(con2.getName()+"5===>"+con2.getParameterCount());

        Student s1 = (Student) con2.newInstance("sun",100);
        System.out.println(s1);
   }
  • 如果是非public的构造器,需要打开权限,然后再创建对象
    setAccessible(boolean)
4.反射获取成员变量对象
  • 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
  • Class类中用于获取成员变量的方法

在这里插入图片描述

@Test
    public void getDeclaredFields(){
        //a.定位Class对象
        Class c = Student.class;
        //b.定位全部成员变量
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName() + "==>" + field.getType());
        }
    }

    /**
     * 2.获取某个成员变量对象
     */
    @Test
    public void getDeclaredField() throws Exception{
        //a.定位Class对象
        Class c = Student.class;
        //b.定位某个成员变量
        Field f = c.getDeclaredField("age");
        System.out.println(f.getName() + "==>" + f.getType());
    }
  • 成员变量赋值、取值
 @Test
    public void setField() throws Exception{
        Class c = Student.class;
        Field ageF = c.getDeclaredField("age");

        ageF.setAccessible(true);
        //赋值
        Student s = new Student();
        ageF.set(s,18);
        System.out.println(s);
        //取值
        int age = (int)ageF.get(s);
        System.out.println(age);
    }
    
5.反射获取方法对象
  • 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象

在这里插入图片描述

  • Object invoke(Object obj, Object… args) ----在某个对象中出发该方法执行
  • 非public的成员方法,需要暴力打开权限
6.反射的作用-绕过编译阶段为集合添加数据
  • 反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素的
  • 泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList,泛型相当于被擦除了
7.反射的作用-通用框架的底层原理

三、注解

(1)注解概述、作用

  • Java注解又称Java标注,是JDK5引入的一种注解机制
  • Java语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注

(2)注解的作用

  • 对Java中类、方法、成员变量做标记,然后进行特殊处理
  • eg. @Test方法就可以被当做测试方法执行

(3)自定义注解—格式

public @interface 注解名称{
      public 属性类型 属性名() default 默认值;
}
  • 特殊属性:
    value属性:如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写;但是有多个属性,且多个属性没有默认值,那么value是不能省略的

(4)元注解

  • 就是注解注解的注解
  • 元注解常见的有两个
    a. @Target:约束自定义注解只能在哪些地方使用
    b. @Retention:申明注解的生命周期
    在这里插入图片描述
    (5)注解解析
  • 判断是否存在注解,存在注解就解析出内容
  • 与注解解析相关的接口:
    Annotation:注解的顶级接口,注解都是Annotation类型的对象
    AnnotatedElement:定义与注解解析相关的解析方法
    所有的类成分Class、Method、Field、Constructor,都实现了AnnotatedElement接口,都拥有解析注解的能力。
    在这里插入图片描述
/**
 * 完成注解的解析
 */
public class Demo2 {
    @Test
    public void parseClass(){
        //先得到类对象
        Class c = BookStore.class;
        //判断类上是否存在注解
        if(c.isAnnotationPresent(book.class)){
            //直接获取该注解对象
            book bk = (book)c.getDeclaredAnnotation(d4_annotation.book.class);
            System.out.println(bk.value());
            System.out.println(bk.price());
            System.out.println(Arrays.toString(bk.author()));
        }
    }

    @Test
    public void parseMethod() throws Exception{
        //先得到类对象
        Class c = BookStore.class;
        Method m = c.getDeclaredMethod("test");
        //判断类上是否存在注解
        if(m.isAnnotationPresent(book.class)){
            //直接获取该注解对象
            book bk = (book)m.getDeclaredAnnotation(d4_annotation.book.class);
            System.out.println(bk.value());
            System.out.println(bk.price());
            System.out.println(Arrays.toString(bk.author()));
        }
    }
}


@book(value = "《某某》",price = 99.9,author = {"江添","盛旺"})
class BookStore{
    @book(value = "《不见上仙三百年》",price = 199.9,author = {"木苏里","魔道"})
    public void test(){
    }
}
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)//一直活着,在运行阶段也不消失
public @interface Mytest {

}

(6)注解的应用场景:junit框架

四、动态代理

(1)动态代理概述、入门

什么是代理?
某些场景下对象会找一个代理对象,来辅助自己完成一些工作

//Test
//目标:学习开发出一个动态代理的对象出来,理解动态代理的执行流程
    //1.创建一个对象,对象的类必须实现接口
    public static void main(String[] args) {
        Star s = new Star("杨超越");
        //生成s的代理对象
        Skill s2 = StarAgent.getProxy(s);
        s2.jump();
        s2.sing();
    }
//StarAgent
   public static Skill getProxy(Star obj){
        //为s生成一个代理对象
        return (Skill) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("收定金");
                        //触发对象真正去干活
                        //method 正在调用的方法 args 代表这个方法的参数
                        Object rs = method.invoke(obj,args);
                        System.out.println("收尾款");
                        return rs;
                    }
                });

    }
public class Star implements Skill {
    private String name;

    public Star(String name) {
        this.name = name;
    }


    @Override
    public void jump() {
        System.out.println(name + "开始跳舞");
    }

    @Override
    public void sing() {
        System.out.println(name + "开始唱歌");
    }
}
//接口
public interface Skill {
    void jump();
    void sing();
}

(2)动态代理应用案例:做性能分析、代理的好处小结
public class Test {
    public static void main(String[] args) {
        UserService userService = ProxyUtil.getProxy(new UserServiceimpl());
        System.out.println(userService.login("admin", "123456"));
        System.out.println(userService.selectUsers());
        userService.deleteUser();
    }
}

public class UserServiceimpl implements UserService {

    @Override
    public String login(String loginName, String passWord) {
       String rs = "登录名称和密码错误";
       if("admin".equals(loginName) && "123456".equals(passWord)){
           rs = "登录成功";
       }
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
       return rs;
    }

    @Override
    public void deleteUser() {
        try {
            System.out.println("您正在删除用户数据");
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public String selectUsers() {
        String rs = "查询了10000个用户数据";
        try {
            Thread.sleep(3000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return rs;
    }
}

public interface UserService {
    String login(String loginName, String passWord);
    void deleteUser();
    String selectUsers();
}

public class ProxyUtil {
    /**
     * 通过一个静态方法,为用户业务对象返回一个代理对象
     */
    public static UserService getProxy(UserService obj){
        return (UserService) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        long starTime = System.currentTimeMillis();
                        //真正触发对象的行为执行
                        Object rs = method.invoke(obj,args);
                        long endTime = System.currentTimeMillis();
                        System.out.println( method.getName() +"方法耗时:" + (endTime-starTime)/1000.0 +"s");
                        return rs;
                    }
                });
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值