JUnit单元测试、反射、注解、动态代理、JDK8新特性

  • 概述 : Junit是Java语言编写的第三方单元测试框架(工具类)

  • 作用 : 用来做“单元测试”——针对某个普通方法,可以像main()方法一样独立运行,它专门用于测试某个方法。

  • Junit的使用步骤

  • 1.在模块下创建lib文件夹,把Junit的jar包复制到lib文件夹中

  • 2.选中Junit的jar包,右键选中 add as Library,把JUnit4的jar包添加到classPath中

  • 3.在测试方法上面写上@Test注解

  • 4.执行测试方法

  • public class TestDemo {

        @Test
        public void test1(){
            System.out.println("测试方法test1...");
        }

        @Test
        public void test2(){
            System.out.println("测试方法test2...");
        }

    }

Junit单元测试的注意事项

  • 1.测试方法的权限修饰符一定是public

  • 2.测试方法的返回值类型一定是void

  • 3.测试方法一定没有参数

  • 4.测试方法 的声明之上一定要使用@Test注解

  • Junit其他注解

  • @Before:用来修饰方法,该方法会在每一个测试方法执行之前执行一次。

  • @After:用来修饰方法,该方法会在每一个测试方法执行之后执行一次。

  • @BeforeClass:用来修饰静态方法,该方法会在所有测试方法之前执行一次,而且只执行一次。

  • @AfterClass:用来修饰静态方法,该方法会在所有测试方法之后执行一次,而且只执行一次。

  • Junit断言

  • 断言:预先判断某个条件一定成立,如果条件不成立,则直接报错。 使用Assert类中的assertEquals()方法

  • public class TestDemo {


        @Test
        public void test(){
            // 断言
            /*
                Assert.assertEquals(参数1,参数2): 断言
                参数1: 期望的值
                参数2: 实际的值
                如果期望的值与实际的值相等,就不报错,如果不相等,就报错
             */
            int sum = getSum(10, 20);
            Assert.assertEquals(30,sum);

        }


        /**
         * 计算2个数的和
         * @param num1
         * @param num2
         * @return 和
         */
        public int getSum(int num1,int num2){
            return num1 * num2;
        }
    }

反射

类的加载

  1. 创建类的实例。

  2. 类的静态变量,或者为静态变量赋值。

  3. 类的静态方法。

  4. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。

  5. 初始化某个类的子类对象。

  6. 直接使用java.exe命令来运行某个主类。

    以上六种情况的任何一种,都可以导致JVM将一个类加载到方法区。

类加载器:是负责将磁盘上的某个class文件读取到内存并生成Class的对象

public class Test {
    public static void main(String[] args) {
        // 需求:获取Person类的类加载器
        // 1.获取Person类的字节码对象
        // 2.使用字节码对象调用getClassLoader()方法
        ClassLoader classLoader = Person.class.getClassLoader();
        System.out.println("Person类的类加载器:"+classLoader);

        // 需求:获取String类的类加载器
        ClassLoader classLoader1 = String.class.getClassLoader();
        System.out.println("String类的类加载器:"+classLoader1);
        // API中说明:一些实现可能使用null来表示引导类加载器。 如果此类由引导类加载器加载,则此方法将在此类实现中返回null
    }
}

扩展类加载器结合Properties的使用

public class Utils {

    public static String value1;
    public static String value2;
    public static String value3;
    public static String value4;

    static {
        try {
            // 1.创建Properties对象
            Properties pro = new Properties();

            // 2.调用load方法加载配置文件中的键值对
            //pro.load(new FileInputStream("day13\\src\\db.properties"));
            // 这种方式获得的流,路径已经到了src路径
            InputStream is = Utils.class.getClassLoader().getResourceAsStream("db.properties");
            pro.load(is);

            // 3.获取数据
            value1 = pro.getProperty("k1");
            value2 = pro.getProperty("k2");
            value3 = pro.getProperty("k3");
            value4 = pro.getProperty("k4");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class Test {
    public static void main(String[] args) throws Exception{
        System.out.println(Utils.value1);
        System.out.println(Utils.value2);
        System.out.println(Utils.value3);
        System.out.println(Utils.value4);
    }
}

反射的引入

通过反射技术对类进行了解剖得到了类的所有成员。

反射的概念

 反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖并操作类中的所有成员(成员变量,成员方法,构造方法)

使用反射操作类成员的前提

要获得该类字节码文件对象,就是Class对象

反射在实际开发中的应用

* 开发IDE(集成开发环境),比如IDEA,Eclipse
* 各种框架的设计和学习 比如Spring,Hibernate,Struct,Mybaits....

获取Class对象

public class Test {
    public static void main(String[] args) throws Exception{
        //- 通过类名.class获得
        Class<Person> c1 = Person.class;

        //- 通过对象名.getClass()方法获得
        Person p = new Person();
        Class<? extends Person> c2 = p.getClass();

        //- 通过Class类的静态方法获得: static Class forName("类全名")
        Class<?> c3 = Class.forName("com.itheima.demo7_获取Class对象.Person");

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c1 == c2);// true
        System.out.println(c2 == c3);// true
    }

Class类常用方法

String getSimpleName(); 获得类名字符串:类名
String getName();  获得类全名:包名+类名
T newInstance() ;  创建Class对象关联类的对象---相当于调用该类的空参构造方法

public class Test {
    public static void main(String[] args)throws Exception {
        // 获取Person类的字节码对象
        Class<Person> c = Person.class;

        //String getSimpleName(); 获得类名字符串:类名
        System.out.println("类的名称:" + c.getSimpleName());

        //String getName();  获得类全名:包名+类名
        System.out.println("类的全名: " + c.getName());

        //T newInstance() ;  创建Class对象关联类的对象---相当于调用该类的空参构造方法
        Person p = c.newInstance(); // Person p = new Person();
        System.out.println(p);
    }
}

反射之操作构造方法

Constructor类概述
    * 类中的每一个构造方法都是一个Constructor类的对象

Class类的方法 
1. Constructor getConstructor(Class... parameterTypes)
        * 根据参数类型获得对应的Constructor对象。
        * 只能获得public修饰的构造方法
 2. Constructor getDeclaredConstructor(Class... parameterTypes)---推荐
        * 根据参数类型获得对应的Constructor对象
        * 可以是public、protected、(默认)、private修饰符的构造方法。
 3. Constructor[] getConstructors()
        获得类中的所有构造方法对象,只能获得public的
 4. Constructor[] getDeclaredConstructors()---推荐
        获得类中的所有构造方法对象
        可以是public、protected、(默认)、private修饰符的构造方法。

通过反射执行构造方法

Constructor对象常用方法
1. T newInstance(Object... initargs)
     根据指定的参数创建对象
    参数:被执行的构造方法需要的实际参数
2. void setAccessible(true)
   设置"暴力反射"——是否取消权限检查,true取消权限检查,false表示不取消

反射之操作成员方法

Method类概述
    * 每一个成员方法都是一个Method类的对象。

Class类中与Method相关的方法
* Method getMethod(String name,Class... args);
    * 根据方法名和参数类型获得对应的成员方法对象,只能获得public的

* Method getDeclaredMethod(String name,Class... args);----->推荐
    * 根据方法名和参数类型获得对应的成员方法对象,包括public、protected、(默认)、private的
      参数1:要获取的方法的方法名
      参数2:要获取的方法的形参类型的Class对象

* Method[] getMethods();
    * 获得类中的所有成员方法对象,返回数组,只能获得public修饰的且包含父类的

* Method[] getDeclaredMethods();----->推荐
    * 获得类中的所有成员方法对象,返回数组,只获得本类的,包括public、protected、(默认)、private的

通过反射获取类的成员变量

Class类中的方法

* Field getField(String name);
    *  根据成员变量名获得对应Field对象,只能获得public修饰
        参数:属性名
* Field getDeclaredField(String name);----->推荐
    *  根据成员变量名获得对应Field对象,包括public、protected、(默认)、private的
        参数:属性名
            
* Field[] getFields();
    * 获得所有的成员变量对应的Field对象,只能获得public的
* Field[] getDeclaredFields();---->推荐
    * 获得所有的成员变量对应的Field对象,包括public、protected、(默认)、private的

通过反射访问成员变量

Field对象常用方法
给对象的属性赋值的方法
    void  set(Object obj, Object value) ----->推荐
    参数1: 给哪个对象的属性赋值---该类的对象
    参数2: 给属性赋的值
        
    void setInt(Object obj, int i)     
    void setLong(Object obj, long l)
    void setBoolean(Object obj, boolean z) 
    void setDouble(Object obj, double d) 
    ...
获取对象属性的值的方法
    Object get(Object obj)  ----->推荐
    int    getInt(Object obj) 
    long getLong(Object obj) 
    boolean getBoolean(Object ob)
    double getDouble(Object obj) 
    ...

void setAccessible(true);暴力反射,设置为可以直接访问私有类型的属性。 ----->推荐
Class getType(); 获取属性的类型,返回Class对象。

注解

  • 注解(annotation),是一种代码级别的说明,和类 接口平级关系.

    • 注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,以后,javac编译器、开发工具和其他程序可以通过反射来了解你的类及各种元素上有无标记,看你的程序有什么标记,就去干相应的事

    • 我们之前使用过的注解:

      1).@Override:子类重写方法时——编译时起作用

      2).@FunctionalInterface:函数式接口——编译时起作用

      3).@Test:JUnit的测试注解——运行时起作用

    • 生成帮助文档@author和@version

    • 执行编译期的检查 例如:@Override

    • 框架的配置(框架=代码+配置)

    • JDK提供的三个基本的注解

      @Override:描述方法的重写.

      @SuppressWarnings:压制\忽略警告.

      @Deprecated:标记过时

自定义注解

public @interface 注解名{
    注解属性
}

使用注解

// 没有属性的注解
public @interface MyAnnotation1 {
}


// 有属性的注解
public @interface MyAnnotation2 {
    String name();
    int age();
}

  • 一旦注解有属性了,使用注解的时候,属性必须有值

  • 若属性类型是一维数组的时候,当数组的值只有一个的时候可以省略{}

  • 如果注解中只有一个属性,并且属性名为value,那么使用注解给注解属性赋值的时候,注解属性名value可以省略

  • 注解属性可以有默认值 格式:属性类型 属性名() defaul t 默认值;

元注解

定义在注解上的注解(修饰注解的注解)

@Target:表示该注解作用在什么上面(位置),默认注解可以在任何位置. 值为:ElementType的枚举值

  • 方法引用使用一对冒号 :: , 方法引用就是用来在一定的情况下,替换Lambda表达式

JDK8新特性

  • 方法引用使用一对冒号 :: , 方法引用就是用来在一定的情况下,替换Lambda表达式

  • 如果一个Lambda表达式大括号中的代码和另一个方法中的代码一模一样,那么就可以使用方法引用把该方法引过来,从而替换Lambda表达式

  • 如果一个Lambda表达式大括号中的代码就是调用另一方法,那么就可以使用方法引用把该方法引过来,从而替换Lambda表达式

  • public class Test {

        public static void printStr(){
            System.out.println("Hello World...");
            System.out.println("Hello World...");
            System.out.println("Hello World...");
        }

        public static void main(String[] args) {
            // 创建并启动线程
           /* new Thread(()->{
                System.out.println("Hello World...");
                System.out.println("Hello World...");
                System.out.println("Hello World...");
            }).start();*/

            /*new Thread(()->{
                Test.printStr();
            }).start();*/

            new Thread(Test::printStr).start();

        }
    }

  • 构造方法引用

  • public class Test1_引用构造方法 {
        public static void main(String[] args) {
             /*
                引入构造方法的格式: 类名::new
             */
            //创建集合
            ArrayList<String> list = new ArrayList<>();
            list.add("杨紫");
            list.add("迪丽热巴");
            list.add("陈钰琪");

            // 需求: 使用Stream流把集合中的元素转换为Person对象,打印输出
            //list.stream().map((String name)->{return new Person(name);}).forEach(p->System.out.println(p));
            // map方法中的Lambda表达式大括号中就是调用Person类的构造方法,可以使用方法引用
            list.stream().map(Person::new).forEach(p->System.out.println(p));
        }
    }

  • 静态方法引用

  • public class Test2_引用静态方法 {
        public static void main(String[] args) {
              /*
                引用静态方法的格式: 类名::方法名
             */
            //创建集合
            ArrayList<String> list = new ArrayList<>();
            list.add("110");
            list.add("111");
            list.add("112");

            // 需求: 使用Stream流把集合中的元素转换为int值,打印输出
            //list.stream().map((String str)->{return Integer.parseInt(str);}).forEach(i-> System.out.println(i+1));
            // map方法的Lambda表达式大括号中就是调用Integer的parseInt方法,可以使用方法引用
            list.stream().map(Integer::parseInt).forEach(i-> System.out.println(i+1));
        }
    }

    有参数成员方法引用

  • 成员方法有参数

  • public class Test3_引用有参数的成员方法 {
        public static void main(String[] args) {
              /*
                成员方法有参数引用:  对象名::方法名
             */
            //创建集合
            ArrayList<String> list = new ArrayList<>();
            list.add("杨紫");
            list.add("迪丽热巴");
            list.add("陈钰琪");

            // 需求:使用Stream流把集合中所有元素打印输出
            //list.stream().forEach(name-> System.out.println(name));
            // froEach方法的Lambda表达式就是调用System.out的println()方法,可以使用方法引用
            list.stream().forEach(System.out::println);


        }
    }

  • 没有参数成员方法引用

  • public class Test4_引用没有参数的成员方法 {
        public static void main(String[] args) {
             /*
                成员方法没有参数引用: 类名::方法名
             */
            //创建集合
            ArrayList<String> list = new ArrayList<>();
            list.add("杨紫");
            list.add("迪丽热巴");
            list.add("陈钰琪");

            // 需求: 使用Stream流把集合中的元素转换为该元素对应的字符长度,打印输出
            //list.stream().map((String name)->{return name.length();}).forEach(System.out::println);
            // map方法的Lambda表达式大括号中就是调用String类的length方法,可以使用方法引用
            list.stream().map(String::length).forEach(System.out::println);

        }
    }

  • Base64

  • static Base64.Decoder getDecoder() 基本型 base64 解码器。
    static Base64.Encoder getEncoder() 基本型 base64 编码器。

    static Base64.Decoder getMimeDecoder() Mime型 base64 解码器。
    static Base64.Encoder getMimeEncoder() Mime型 base64 编码器。

    static Base64.Decoder getUrlDecoder() Url型 base64 解码器。
    static Base64.Encoder getUrlEncoder() Url型 base64 编码器。

Encoder编码器:  encodeToString(byte[] bys)编码
Decoder解码器:  decode(String str) 解码

public class Test1 {
    public static void main(String[] args) {
        // 使用基本型的编码器和解码器对数据进行编码和解码:
        // 1.获取编码器
        Base64.Encoder encoder = Base64.getEncoder();

        // 2.对字符串进行编码
        String str = "name=中国?password=123456";
        String str1 = encoder.encodeToString(str.getBytes());

        // 3.打印输出编码后的字符串
        System.out.println("编码后的字符串:"+str1);

        // 4.获取解码器
        Base64.Decoder decoder = Base64.getDecoder();

        // 5.对编码后的字符串进行解码
        byte[] bys = decoder.decode(str1);
        String str2 = new String(bys);

        // 6.打印输出解码后的字符串
        System.out.println("解码后的字符串:"+str2);
    }
}

  • URL

  • public class Test2 {
        public static void main(String[] args) {

            // 使用URL型的编码器和解码器对数据进行编码和解码:
            // 1.获取编码器
            Base64.Encoder encoder = Base64.getUrlEncoder();

            // 2.对字符串进行编码
            String str = "name=中国?password=123456";
            String str1 = encoder.encodeToString(str.getBytes());

            // 3.打印输出编码后的字符串
            System.out.println("编码后的字符串:"+str1);

            // 4.获取解码器
            Base64.Decoder decoder = Base64.getUrlDecoder();

            // 5.对编码后的字符串进行解码
            byte[] bys = decoder.decode(str1);
            String str2 = new String(bys);

            // 6.打印输出解码后的字符串
            System.out.println("解码后的字符串:"+str2);
        }
    }

  • MIME

  • public class Test3 {
        public static void main(String[] args) {
            // 使用MIME型的编码器和解码器对数据进行编码和解码:
            // 1.获取编码器
            Base64.Encoder encoder = Base64.getMimeEncoder();

            // 2.对字符串进行编码
            String str = "";
            for (int i = 0; i < 100; i++) {
                str += i;
            }
            System.out.println("编码前的字符串:"+str);

            String str1 = encoder.encodeToString(str.getBytes());

            // 3.打印输出编码后的字符串
            System.out.println("编码后的字符串:"+str1);

            // 4.获取解码器
            Base64.Decoder decoder = Base64.getMimeDecoder();

            // 5.对编码后的字符串进行解码
            byte[] bys = decoder.decode(str1);
            String str2 = new String(bys);

            // 6.打印输出解码后的字符串
            System.out.println("解码后的字符串:"+str2);
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值