Java进阶13讲__补充1/2

单元测试、反射、注解、Lombok

1.  单元测试

1.1  Junit单元测试框架

1.2  Junit框架入门

package com.itheima.a_单元测试;

import org.junit.Test;

public class SpringUtilTest {
    @Test
    public void testPrintNumber() {
        StringUtil.printNumber("Jack");
        StringUtil.printNumber("张三");
        StringUtil.printNumber("");
        StringUtil.printNumber(null);
    }
}

1.3  Junit框架的常见注解

package com.itheima.a_单元测试;

import org.junit.*;

public class SpringUtilTest {
    @Before
    public void init() {
        System.out.println("===init===");
    }

    @After
    public void destroy() {
        System.out.println("===destroy===");
    }

    @BeforeClass
    public static void initClass() {
        System.out.println("===initClass===");
    }

    @AfterClass
    public static void destroyClass() {
        System.out.println("===destroyClass===");
    }

    @Test
    public void testPrintNumber() {
        StringUtil.printNumber("Jack");
        StringUtil.printNumber("张三");
        StringUtil.printNumber("");
    }

    @Test
    public void testGetMaxIndex() {
        StringUtil su = new StringUtil();
        int i = su.getMaxIndex("我是孙庆的爹");
        System.out.println("i:" + i);
    }
}

1.4  Junit框架断言

package com.itheima.a_单元测试;

import org.junit.Assert;
import org.junit.Test;

public class SpringUtilTest {

    @Test
    public void testGetMaxIndex() {
        StringUtil su = new StringUtil();
        int i0 = su.getMaxIndex("我是孙庆的爹");
        Assert.assertEquals("NotEquals", 5, i0);
    }
}

2.  反射

2.1  认识反射、获取类 

package com.itheima.b_反射;

/*
反射的第一步是什么
    获取Class类对象,如此才可以解析类的全部成分

获取Class对象的三种方式
    1. 直接使用类名.class获取:Class c1 = 类名.class
    2. 调用Class提供的方法:Class c2 = Class.forName("全类名")
    3. 调用Object提供的方法:Class c3 = 对象.getClass()
*/
public class Demo1 {
    public static void main(String[] args) throws Exception {
        Class c1 = Cat.class;
        System.out.println(c1.getName());
        Class c2 = Class.forName("com.itheima.b_反射.Cat");
        System.out.println(c2.getName());
        Class c3 = new Cat().getClass();
        System.out.println(c3.getName());
    }
}

2.2  获取类的构造器

有Declared的方法是拿所有的,没有Declared修饰的是拿公共的(public)

package com.itheima.b_反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;

/*
获取构造器[下面是Class的方法]
    Constructor<?>[] getConstructors()	获取所有的公共构造器(只能获取public修饰的)
    Constructor<?>[] getDeclaredConstructors()	获取全部构造器(只要存在就能拿到)
    Constructor<T> getConstructor(Class<?>... parameterTypes)	获取某个公共构造器(只能获取public修饰的)
    Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)	获取某个构造器(只要存在就能拿到)

使用构造器(创建对象)[下面是Constructor的方法]
    T newInstance(Object... initArgs)	调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
    public void  setAccessible(boolean flag)	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰构造器反射创建对象,需要暴力反射(禁止JVM检查构造方法的访问权限)
*/
public class Demo2 {
    public static void main(String[] args) throws Exception {
        Class myClass = new Cat().getClass();
//        Constructor<?>[] getConstructors()	获取所有的公共构造器(只能获取public修饰的)
        Constructor[] constructors = myClass.getConstructors();
//        Arrays.stream(constructors).forEach(System.out::println);
//        System.out.println();

//        Constructor<?>[] getDeclaredConstructors()	获取全部构造器(只要存在就能拿到)
        Constructor[] declaredConstructors = myClass.getDeclaredConstructors();
//        Arrays.stream(declaredConstructors).forEach(System.out::println);
//        System.out.println();

//        Constructor<T> getConstructor(Class<?>... parameterTypes)	获取某个公共构造器(只能获取public修饰的)
        Constructor<Cat> constructor = myClass.getConstructor();
        Constructor<Cat> constructor1 = myClass.getConstructor(String.class);
//        Constructor<Cat> constructor2 = myClass.getConstructor(String.class, int.class);
//        System.out.println(constructor);
//        System.out.println(constructor1);
//        System.out.println(constructor2);
//        System.out.println();

//        Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)	获取某个构造器(只要存在就能拿到)
        Constructor<Cat> declaredConstructor = myClass.getDeclaredConstructor(String.class, int.class);
//        System.out.println(declaredConstructor);

//          使用公告构造器创建对象
        Cat cat = constructor.newInstance();
        System.out.println(cat);
//          使用私有构造器创建对象
        declaredConstructor.setAccessible(true);//暴力反射
        Cat cat1 = declaredConstructor.newInstance("招财猫", 21);
        System.out.println(cat1);
    }

}

2.3  获取类的成员变量

package com.itheima.b_反射;

import java.lang.reflect.Field;
import java.util.Arrays;

/*
获取成员变量[Class提供]
    public Field[] getFields()	获取类的所有公共成员变量(只能获取public修饰的)
    public Field[] getDeclaredFields()	获取类的全部成员变量(只要存在就能拿到)
    public Field getField(String name)	获取类的某个公共成员变量(只能获取public修饰的)
    public Field getDeclaredField(String name)	获取类的某个成员变量(只要存在就能拿到)

使用成员变量(赋值和取值) [Field提供]
    public void set(Object obj, Object value): 赋值
    public Object get(Object obj):	取值
    public void  setAccessible(boolean flag):	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰的变量,需要暴力反射
*/
public class Demo3 {
    public static void main(String[] args) throws Exception {
        Cat cat = new Cat();
        Class<? extends Cat> catClass = cat.getClass();
//    public Field getDeclaredField(String name)	获取类的某个成员变量(只要存在就能拿到)
        Field name = catClass.getDeclaredField("name");
        Field country = catClass.getDeclaredField("COUNTRY");
        Field age = catClass.getDeclaredField("age");
        //获取成员变量[Class提供]
        //    public Field[] getFields()	获取类的所有公共成员变量(只能获取public修饰的)
//        Field[] fields = catClass.getFields();
//        Arrays.stream(fields).forEach(System.out::println);
//        System.out.println();

        //    public Field[] getDeclaredFields()	获取类的全部成员变量(只要存在就能拿到)
//        Field[] declaredFields = catClass.getDeclaredFields();
//        Arrays.stream(declaredFields).forEach(item-> System.out.println(item.getName()+"类型:"+item.getType()));
        //    public Field getField(String name)	获取类的某个公共成员变量(只能获取public修饰的)
//        Field name = catClass.getField("name");
//        System.out.println(name);

        //使用成员变量(赋值和取值) [Field提供]
        System.out.println("======");
        System.out.println(name.getName());
        System.out.println(age.getName());
        System.out.println("======");
        System.out.println(cat);
        //    public void set(Object obj, Object value): 赋值
        String countryStr = (String) country.get(country);
        System.out.println(countryStr);
        //    public void  setAccessible(boolean flag):	设置为true,表示禁止检查访问控制(暴力反射)
        name.setAccessible(true);
        age.setAccessible(true);

        name.set(cat, "孙庆");
        age.set(cat, 21);
        System.out.println(cat);
        //    public Object get(Object obj):	取值
        String catName = (String) name.get(cat);
        System.out.println(catName);
        int catAge = (int) age.get(cat);
        System.out.println(catAge);
        System.out.println("======");
    }

}

2.4  获取类的成员方法

package com.itheima.b_反射;

import java.lang.reflect.Method;
import java.util.Arrays;

/*
获取成员方法[Class提供]
    Method[] getMethods()	获取类的全部公共成员方法(只能获取public修饰的)
    Method[] getDeclaredMethods()	获取类的全部成员方法(只要存在就能拿到)
    Method getMethod(String name, Class<?>... parameterTypes) 	获取类的某个公共成员方法(只能获取public修饰的)
    Method getDeclaredMethod(String name, Class<?>... parameterTypes)	获取类的某个成员方法(只要存在就能拿到)

使用成员方法(执行方法)[Method提供]
    public Object invoke(Object obj, Object... args)	触发某个对象的该方法执行。
    public void  setAccessible(boolean flag)	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰的成员方法,需要暴力反射
*/
public class Demo4 {
    public static void main(String[] args) throws Exception {
        Cat cat = new Cat();
        Class<? extends Cat> catClass = cat.getClass();
        //获取成员方法[Class提供]
        //Method[] getMethods()	获取类的全部公共成员方法(只能获取public修饰的)
//        Method[] methods = catClass.getMethods();
        //Method[] getDeclaredMethods()	获取类的全部成员方法(只要存在就能拿到)
        System.out.println("================");
        Method[] methodsArr = catClass.getDeclaredMethods();
        //        Arrays.stream(methods).forEach(item -> {
//            System.out.println("方法名字:" + item.getName() + ",返回值类型:" + item.getReturnType() + ",参数个数:" + item.getParameterCount());
//        });
        //Method getMethod(String name, Class<?>... parameterTypes) 	获取类的某个公共成员方法(只能获取public修饰的)
//        Method method = catClass.getMethod(cat.getName());
//        System.out.println(method);
        //Method getDeclaredMethod(String name, Class<?>... parameterTypes)	获取类的某个成员方法(只要存在就能拿到)
        Method eat = catClass.getDeclaredMethod("eat", String.class);
        System.out.println(eat.getReturnType());
        System.out.println(Arrays.toString(eat.getParameterTypes()));
        //使用成员方法(执行方法)[Method提供]
        //public Object invoke(Object obj, Object... args)	触发某个对象的该方法执行。
        //public void  setAccessible(boolean flag)	设置为true,表示禁止检查访问控制(暴力反射)
        eat.setAccessible(true);
        System.out.println(eat.invoke(cat, "鱼"));

    }
}

2.5  作用、应用场景

2.6  案例

package com.itheima.b_反射;

import java.lang.reflect.Field;
import java.util.Arrays;

/*
反射案例
    对于任意一个对象,该框架都可以把对象的字段名和对应的值,然后打印在控制台

*/
public class Demo5 {
    public static void main(String[] args) {
        //1. 准备两个对象
        Student student = new Student("柳岩", 40, '女', 167.5, "女星");
        Teacher teacher = new Teacher("播妞", 6000);
        //2.调用方法
        printInfo(student);
        printInfo(teacher);
    }

    public static void printInfo(Object o) {
        Class<?> obj = o.getClass();
        Field[] list = obj.getDeclaredFields();
        System.out.println("======" + obj.getSimpleName() + "======");
        Arrays.stream(list).forEach(item -> {
            try {
                item.setAccessible(true);
                System.out.println(item.getName() + "=" + item.get(o));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}

class Student {
    public Student(String name, int age, char sex, double height, String hobby) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
        this.hobby = hobby;
    }

    private String name;
    private int age;
    private char sex;
    private double height;
    private String hobby;
}

class Teacher {
    public Teacher(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    private String name;
    private double salary;
}

3.  注解

3.1  快速入门

package com.itheima.c_annotation.example;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassNameCheck {
    public String[] author() default "佚名";

    public String value();
}

3.2  注解解析

3.3  注解属性

package com.itheima.c_annotation.example;

import com.itheima.c_annotation.ClassUtil;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class checkClassName {
    public static void isRight() throws Exception {
        StringBuilder sb = new StringBuilder();
        //拿集合
        Set<Class> classSet = ClassUtil.getClasses("com.itheima.c_annotation.example");
        //遍历
        System.out.println("------------");
        List<Class> list = classSet.stream()
                .filter(e -> e.isAnnotationPresent(ClassNameCheck.class))
                .filter(e -> !e.getSimpleName().startsWith("Heima"))
                .collect(Collectors.toList());
        if (list.size() != 0) {
            list.stream().forEach(e -> {
                ClassNameCheck annotation = (ClassNameCheck) e.getDeclaredAnnotation(ClassNameCheck.class);
                System.out.print(e.getSimpleName() + "作者:");
                Arrays.stream(annotation.author()).forEach(System.out::print);
                System.out.println(",作用:" + annotation.value());
            });
            throw new Exception("类名不规范");
        }
        System.out.println("------------");
    }
}

获取某个包下所有的类 

package com.itheima.c_annotation;


import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileFilter;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import static cn.hutool.core.util.ClassUtil.getClassLoader;
public class ClassUtil {
    private ClassUtil() {
    }


    /**
     * 获取某个包下的所有类
     */
    public static Set<Class> getClasses(String packageName) {
        try {
            Set<Class> classSet = new HashSet<>();
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageName.replace(".", "/"));
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                if (url != null) {
                    String protocol = url.getProtocol();
                    if (protocol.equals("file")) {
                        String packagePath = url.getPath().replaceAll("%20", " ");
                        addClass(classSet, packagePath, packageName);
                    } else if (protocol.equals("jar")) {
                        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                        if (jarURLConnection != null) {
                            JarFile jarFile = jarURLConnection.getJarFile();
                            if (jarFile != null) {
                                Enumeration<JarEntry> jarEntries = jarFile.entries();
                                while (jarEntries.hasMoreElements()) {
                                    JarEntry jarEntry = jarEntries.nextElement();
                                    String jarEntryName = jarEntry.getName();
                                    if (jarEntryName.endsWith(".class")) {
                                        String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
                                        doAddClass(classSet, className);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return classSet;
        } catch (Exception e) {
            throw new RuntimeException("包名错误");
        }


    }

    private static void addClass(Set<Class> classSet, String packagePath, String packageName) {
        File[] files = new File(packagePath).listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
            }
        });
        for (File file : files) {
            String fileName = file.getName();
            if (file.isFile()) {
                String className = fileName.substring(0, fileName.lastIndexOf("."));
                if (StringUtils.isNotEmpty(packageName)) {
                    className = packageName + "." + className;
                }
                doAddClass(classSet, className);
            } else {
                String subPackagePath = fileName;
                if (StringUtils.isNotEmpty(packagePath)) {
                    subPackagePath = packagePath + "/" + subPackagePath;
                }
                String subPackageName = fileName;
                if (StringUtils.isNotEmpty(packageName)) {
                    subPackageName = packageName + "." + subPackageName;
                }
                addClass(classSet, subPackagePath, subPackageName);
            }
        }
    }

    /**
     * 加载类
     */
    private static Class loadClass(String className, boolean isInitialized) {
        Class cls;
        try {
            cls = Class.forName(className, isInitialized, getClassLoader());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return cls;
    }

    /**
     * 加载类(默认将初始化类)
     */
    private static Class loadClass(String className) {
        return loadClass(className, true);
    }

    private static void doAddClass(Set<Class> classSet, String className) {
        Class cls = loadClass(className, false);
        classSet.add(cls);
    }
}

4.  Lombok

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值