java-高级技术(单元测试、反射)
单元测试
对最小功能单元——方法编写代码,进行测试
Junit单元测试框架
可用来对方法进行测试,是第三方公司开源的
- 优点:
可灵活编写测试代码,可针对某个方法执行测试,也支持一键完成对全部方法的自动化测试,且各自独立
不需要程序员分析测试的结果,会自动生成测试报告
/*** 字符串工具类*/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;}
}
// 测试类:JUnit单元测试框架,测试StringUtil类
public class StringUtilTest {//测试方法:公开public,无参,无返回值//测试方法必须加上@Test注解(核心步骤)@Testpublic void testPrintNumber(){//测试步骤StringUtil.printNumber("张三aaa");//5//测试用例StringUtil.printNumber("");StringUtil.printNumber(null);}@Testpublic 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对象
public class ReflectDemo1 {public static void main(String[] args) throws Exception {//掌握反射第一步操作:获取类的class对象//1、获取类本身:类名.classClass 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);}
}
第二步:获取类中的成分,并进行操作
public class ReflectDemo2 {@Testpublic void getClassInfo() {//获取类中的信息//反射第一步:获取类本身Class c1 = Student.class;System.out.println(c1.getName());//类名的全类名 com.it06.junit_reflect_annotation_proxy.demo2reflect.StudentSystem.out.println(c1.getSimpleName());//类名 Student}//2、获取类的构造器对象,并进行操作@Testpublic 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、获取类的成员变量对象,并进行操作@Testpublic 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、获取类的成员方法对象,并进行操作@Testpublic 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、把成员变量名和值写道文件中
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);}
}
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();}
}