java-高级技术(单元测试、反射)

单元测试

对最小功能单元------方法编写代码,进行测试

Junit单元测试框架

可用来对方法进行测试,是第三方公司开源的

  • 优点:
    可灵活编写测试代码,可针对某个方法执行测试,也支持一键完成对全部方法的自动化测试,且各自独立
    不需要程序员分析测试的结果,会自动生成测试报告
java 复制代码
/**
 * 字符串工具类
 */

public class StringUtil {
    public static void printNumber(String name){
        if(name==null){
            System.out.println("请输入字符串");
            return;
        }
        System.out.println("长度是:"+name.length());
    }
    /**
     * 求字符串最大索引
     */
    public static int getMaxIndet(String data){
        if(data==null || "".equals(data)){
            return -1;
        }
        return data.length()-1;
    }
}
java 复制代码
// 测试类:JUnit单元测试框架,测试StringUtil类
public class StringUtilTest {
    //测试方法:公开public,无参,无返回值
    //测试方法必须加上@Test注解(核心步骤)
    @Test
    public void testPrintNumber(){
        //测试步骤
        StringUtil.printNumber("张三aaa");//5
        //测试用例
        StringUtil.printNumber("");
        StringUtil.printNumber(null);

    }

    @Test
    public void testGetMaxIndet(){
        int max = StringUtil.getMaxIndet("abcdef");
        //测试用例
        int max1 = StringUtil.getMaxIndet("");
        int max2 = StringUtil.getMaxIndet(null);

        //断言测试:测试结果与预期结果是否一致
        Assert.assertEquals("本轮测试失败,业务获取最大索引有问题",5,max);
        Assert.assertEquals("本轮测试失败,业务获取最大索引有问题",-1,max1);
        Assert.assertEquals("本轮测试失败,业务获取最大索引有问题",-1,max2);
    }
}

反射

反射:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器)

第一步:获得class对象

java 复制代码
public class ReflectDemo1 {
    public static void main(String[] args) throws Exception {
        //掌握反射第一步操作:获取类的class对象
        //1、获取类本身:类名.class
        Class c1 = Student.class;
        System.out.println(c1);

        //2、获取类本身:Class.forName("全类名")
        Class c2 = Class.forName("com.it06.junit_reflect_annotation_proxy.demo2reflect.Student");
        System.out.println(c2);

        System.out.println(c1==c2);
        //3、获取对象本身:对象.getClass()
        Student s = new Student();
        Class c3 = s.getClass();
        System.out.println(c3);

        System.out.println(c1==c3);
    }
}

第二步:获取类中的成分,并进行操作


java 复制代码
public class ReflectDemo2 {
    @Test
    public void getClassInfo() {
        //获取类中的信息
        //反射第一步:获取类本身
        Class c1 = Student.class;
        System.out.println(c1.getName());//类名的全类名 com.it06.junit_reflect_annotation_proxy.demo2reflect.Student
        System.out.println(c1.getSimpleName());//类名 Student
    }
    //2、获取类的构造器对象,并进行操作
    @Test
    public void getConstructor() throws Exception {
        Class c1 = Dog.class;
        //获取构造器对象
        Constructor[] cons = c1.getDeclaredConstructors();
        for (Constructor c : cons) {
            System.out.println(c.getName() +"("+ c.getParameterCount()+")");
        }
        //3、获取单个构造器对象
        Constructor con = c1.getDeclaredConstructor();
        System.out.println(con.getName() +"("+ con.getParameterCount()+")");

        Constructor con2 = c1.getDeclaredConstructor(String.class,int.class);//2个参数的有参构造器
        System.out.println(con2.getName() +"("+ con2.getParameterCount()+")");

        //4、获取构造器的作用依然是创建对象
        //暴力反射:暴力反射,忽略访问权限修饰符
        con.setAccessible(true);//绕过访问权限
        Dog d1 = (Dog) con.newInstance();
        System.out.println(d1);

        Dog d2 = (Dog) con2.newInstance("小花",2);
        System.out.println(d2);
    }

    //3、获取类的成员变量对象,并进行操作
    @Test
    public void getField() throws Exception {
        //获取Class对象
        Class c1 = Dog.class;
        //获取成员变量对象
        Field[] field = c1.getDeclaredFields();
        for (Field f : field) {
            System.out.println(f.getName() +"("+ f.getType().getName()+")");
        }
        //获取单个成员变量对象
        Field f = c1.getDeclaredField("sex");
        System.out.println(f.getName() +"("+ f.getType().getName()+")");

        Field f2 = c1.getDeclaredField("age");
        System.out.println(f2.getName() +"("+ f2.getType().getName()+")");

        //4、获取成员变量的作用依然是取值和赋值
        Dog d1 = new Dog( "小花", 2);
        f.setAccessible(true);//绕过访问权限
        f.set(d1, "female");
        System.out.println(d1);

        String sex = (String) f.get(d1);
        System.out.println(sex);
    }

    //4、获取类的成员方法对象,并进行操作
    @Test
    public void getMethod() throws Exception {
        //获取Class对象
        Class c1 = Dog.class;
        //获取成员方法对象
        Method[] methods = c1.getDeclaredMethods();
        for (Method m : methods) {
            System.out.println(m.getName() +"("+ m.getParameterCount()+")");
        }
        //获取单个成员方法对象
        Method m = c1.getDeclaredMethod("show");//获取无参数的show方法
        Method m2 = c1.getDeclaredMethod("show",String.class);//获取有参数的show方法
        System.out.println(m.getName() +"("+ m.getParameterCount()+")");
        System.out.println(m2.getName() +"("+ m2.getParameterCount()+")");

        //5、获取成员方法的作用依然是调用方法
        Dog d1 = new Dog( "小花", 2);
        m.setAccessible(true);
        Object rs1 = m.invoke(d1);//唤醒d1的show方法执行,相当于d1.show()
        System.out.println(rs1);

        Object rs2 = m2.invoke(d1, "小黑");
        System.out.println(rs2);
    }
}

作用、应用场景

  • 基本作用:得到一个类的全部成分然后操作
  • 破坏封装性
  • 绕过泛型的约束
  • 最重要的用途:做java的框架,基本主流框架都会基于反射设计一些通用功能。

使用反射做一个简易版框架

需求:

对任意一个对象,该框架可以把对象字段名和对应的值保存到文件中
步骤

1、定义一个方法接收任何对象

2、每收到一个对象 ,使用反射获取该对象的class对象,然后获取全部的成员变量

3、遍历成员变量,然后提取成员变量在该对象中的具体值

4、把成员变量名和值写道文件中

java 复制代码
public class ReflectDemo4 {
    public static void main(String[] args) throws Exception {
        //搞清反射的应用:做框架的通用技术
        Dog dog = new Dog("张三", 5);
        saveObject(dog);

        //创建学生对象
        Student s = new Student( "方源", 500,"炼蛊");
        saveObject(s);
        //创建老师对象
        Teacher t = new Teacher("星宿", 20000, "占卜",5000,"天庭","female");
        saveObject(t);
    }
}
java 复制代码
public class SaveObjectFrameWork {
    //保存任意对象的静态方法
    public static void saveObject(Object obj) throws Exception {
        PrintStream ps = new PrintStream(new FileOutputStream("D:\\javacode\\javaseaimax\\product/src/obj.txt", true));
        //obj可能是任意对象
        //只有反射能知道对象有多少字段
        //1、获取Class对象
        Class c1 = obj.getClass();
        String name = c1.getSimpleName();
        ps.println("============="+name+"================");
        //2、获取Class对象所有字段
        Field[] fields = c1.getDeclaredFields();
        //3、遍历字段
        for (Field f : fields) {
            //4、获取字段名称
            String fieldName = f.getName();
            //5、获取字段值
            f.setAccessible(true);
            Object fieldValue = f.get(obj) + "";
            //6、打印到文件
            ps.println(fieldName + ":" + fieldValue);
        }
        ps.close();
    }
}
相关推荐
DokiDoki之父3 小时前
Web核心—JSP入门/EL/JSTL标签/MVC+三层架构/一文速通
java·开发语言
独自破碎E3 小时前
Leetcode2166-设计位集
java·数据结构·算法
Cikiss3 小时前
LeetCode160.相交链表【最通俗易懂版双指针】
java·数据结构·算法·链表
很㗊3 小时前
C与C++---指针、引用、结构体及内存管理
c语言·开发语言
怪力左手3 小时前
地图下载工具
开发语言·ios·swift
wjs20244 小时前
C 标准库 - `<time.h>`
开发语言
聪明的笨猪猪4 小时前
Java Redis “Sentinel(哨兵)与集群”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
222you4 小时前
Mybatis(1)
java·tomcat·mybatis
靠近彗星4 小时前
1.5操作系统引导
java·linux·服务器·操作系统