赞
踩
针对最小的功能单元(方法),编写测试代码对其进行正确性测试。
main方法进行单元测试的问题:
Junit单元测试框架
Junit使用步骤
自动化测试
在项目上右键Run All Test
案例
工具类
public class StringUtil {
public static void printNumber(String name) {
System.out.println("名字的长度是:" + name.length());
}
// 求最大索引
public static int getMaxIndex(String data) {
if (data == null) {
return -1;
}
return data.length();
}
}
测试类
public class StringUtilTest { @Test public void testPrintNumber() { StringUtil.printNumber("admin"); // StringUtil.printNumber(null); } @Test public void testGetMaxIndex() { int r1 = StringUtil.getMaxIndex("admin"); // 断言,看实际期望的和程序输出的是否有出入 Assert.assertEquals("有问题", 4, r1); } }
Junit框架的常见注解
在测试方法之前执行的方法——初始化资源
在测试方法之后执行的方法——释放资源
测试类
public class StringUtilTest { @Before // 每个测试方法执行之前执行一次 public void test1() { System.out.println("----"); } @BeforeClass // 所有测试方法执行之前执行一次 public static void test11() { System.out.println("String测试类开始执行了"); } @After // 每个测试方法执行之后执行一次 public void test2() { System.out.println("===="); } @AfterClass // 所有测试方法执行之前执行一次 public static void test22() { System.out.println("String测试类执行结束了"); } @Test public void testPrintNumber() { StringUtil.printNumber("admin"); // StringUtil.printNumber(null); } @Test public void testGetMaxIndex() { int r1 = StringUtil.getMaxIndex("admin"); System.out.println(r1); // 断言,看实际期望的和程序输出的是否有出入 Assert.assertEquals("有问题", 4, r1); } }
学习框架、理解源码/开发框架
java.lang.reflect
概念: 加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)——反序列化/向外界展示已经封装好的内部东西
学什么: 如何获取类的信息并操作他们
步骤:
1)获取Class对象的三种方式
Class c1 = 类名.class
调用Class提供的方法:public static Class forName(String package);
Object提供的方法:public Class getClass(); Class c3 = 对象.getClass();
public class Test1Class { public static void main(String[] args) throws Exception { // 方式一 Class c1 = Student.class; System.out.println(c1.getName()); // 全类名 com.itheima.d2_reflect.Student System.out.println(c1.getSimpleName()); // 简名 Student // 方式二 Class c2 = Class.forName("com.itheima.d2_reflect.Student"); System.out.println(c2.getName()); // com.itheima.d2_reflect.Student // 方式三,通过类的实例对象 Student s = new Student(); Class c3 = s.getClass(); System.out.println(c3.getName()); // com.itheima.d2_reflect.Student System.out.println(c1 == c2); // true System.out.println(c2 == c3); // true } }
2)获取Constructor对象
类
public class Cat {
private String name;
private int age;
private Cat() {
}
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
}
获取Constructor对象
public class TestConstructor { @Test public void testGetConstructor() { // 1. 首先要获取类的class对象 Class c = Cat.class; // Class.forName("com.itheima.d2_reflect.Cat"); // 对象.getClass() // 2. 获取全部构造器 Constructor[] constructors = c.getConstructors(); // 只能获取public修饰的构造器 for (Constructor constructor : constructors) { System.out.println(constructor.getName() + "--->" + constructor.getParameterCount()); } Constructor[] constructors1 = c.getDeclaredConstructors(); // 获取任何修饰符修饰的构造器 for (Constructor constructor : constructors1) { System.out.println(constructor.getName() + "===>" + constructor.getParameterCount()); } } @Test public void testGetOneConstructor() throws Exception { // 1. 首先要获取类的class对象 Class c = Cat.class; // Class.forName("com.itheima.d2_reflect.Cat"); // 对象.getClass() // 2. 获取1个构造器 Constructor constructor1 = c.getDeclaredConstructor(); // 获取无参构造器 System.out.println(constructor1.getName() + "--->" + constructor1.getParameterCount()); Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class); // 获取任何修饰符修饰的构造器 System.out.println(constructor2.getName() + "===>" + constructor2.getParameterCount()); } }
作用:
初始化对象返回
@Test public void testGetOneConstructor() throws Exception { // 1. 首先要获取类的class对象 Class c = Cat.class; // Class.forName("com.itheima.d2_reflect.Cat"); // 对象.getClass() // 2. 获取1个构造器 Constructor constructor1 = c.getDeclaredConstructor(); // 获取无参构造器 System.out.println(constructor1.getName() + "--->" + constructor1.getParameterCount()); // 重点!!! constructor1.setAccessible(true); // 禁止检查访问权限,也就是不管private还是public,都能创建对象,会破坏封装性 Cat cat = (Cat) constructor1.newInstance(); // 调用此构造器,并传入参数,完成对象的初始化 Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class); // 获取任何修饰符修饰的构造器 System.out.println(constructor2.getName() + "===>" + constructor2.getParameterCount()); }
3)获取成员变量Field
public Field[] getFields()——获取全部public修饰的成员变量
public Field[] getDeclaredFields()——获取全部成员变量
public Field getField(String name)——根据成员变量的名字,获取某个成员变量,只能获取public修饰的
public Field getDeclaredField(String name)——根据成员变量的名字,获取某个成员变量
作用: 赋值、取值
void set(Object obj, Object value);
Object get(Object obj);
public void setAccessible(boolean flag); // 禁止访问权限
4)获取成员方法Method
同上
作用:执行
public Object invoke(Object obj, Object……args); // 出发某个对象的该方法执行
public void setAccessible(boolean flag); /// 设置true,表示禁止检查访问控制
反射的作用
JAVA代码里的特殊标记
作用: 让其他程序根据在注解信息来决定怎么执行该程序
自定义注解: 自己定义注解
格式:
public @interface 注解名称{
public 属性类型 属性名() default 默认值;
}
/*
* 自定义注解
*/
public @interface MyTest1 {
// String value(); // 特殊属性,只有这一个属性时,或者后面是有默认值的,用的时候可以不写名字
String aaa();
boolean bbb() default true;
String[] ccc();
}
@MyTest1(aaa = "小鱼0135", ccc = {"嘻嘻", "嘎嘎"})
public class AnnotationTest1 {
@MyTest1(aaa="小君", bbb=false, ccc={"123"})
public void test1(){
}
}
原理:
元注解:修饰注解的注解
/*
* 自定义注解
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest1 {
// String value(); // 特殊属性,只有这一个属性时,或者后面是有默认值的,用的时候可以不写名字
String aaa();
boolean bbb() default true;
String[] ccc();
}
注解的解析
判断类上、方法上、成员变量上是否存在注解,并把注解里面的内容给解析出来
如何解析注解:
要解析谁上面的注解,就要先拿到谁(要解析类上面的注解,应该先获取该类的Class对象,再通过Class对象解析其上面的注解;Class、Method、Field、Constructor都实现了AnnotatedElement接口,他们都有解析注解的能力)
/* * 注解的解析 * */ public class AnnotationTest3 { @Test public void parseClass() { // 1. 先得到Class对象 Class c = Demo.class; // 2. 解析类上的注解 // 判断类上是否包含了注解 if(c.isAnnotationPresent(MyTest4.class)) { MyTest4 myTest4 = (MyTest4) c.getDeclaredAnnotation(MyTest4.class); System.out.println(myTest4.value()); System.out.println(myTest4.aaa()); System.out.println(Arrays.toString(myTest4.bbb())); } } }
应用场景:结合反射等做框架
整理:就是做框架的时候会自定义很多注解,说明怎么执行这段程序(功能),那别人使用这个功能就要完成一些操作,这个时候就要用到反射,拿出类信息、构造器信息、成员变量和方法等信息,执行一些初始化、取值赋值、执行等一些操作。
程序为什么需要代理
对象如果干的事太多,可以通过代理来转移部分职责
代理的样子
对象有什么方法想被代理,代理一定要有对应的方法
代理如何知道有什么方法需要代理
接口:想代理的方法
案例:
BigStar
public class BigStar implements Star{ private String name; public BigStar(String name) { this.name = name; } // 唱歌行为 public String sing(String name) { System.out.println(this.name + "正在唱" + name); return "唱完了!谢谢大噶!"; } // 跳舞行为 public void dance() { System.out.println(this.name + "正在跳舞!"); } }
想要代理的接口类Star
// 指明有哪些方法需要被代理
public interface Star {
String sing(String name);
void dance();
}
代理对象的类
public class ProxyUtil { // 生成代理对象,并返回 public static Star creatrProxy(BigStar bigStar) { // Java为产生代理,设计了Proxy类。java.lang.reflect /* newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)*/ // 参数1:用于指定一个类的加载器 // 参数2:指定生成的代理的样子,也就是方法,接口数组 // 参数3:指定生成的代理对象要干什么事情,InvocationHandler是一个接口,也就是要实现一个匿名内部类,指定对象要要干的事情 Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{Star.class}, new InvocationHandler() { @Override // 回调方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 代理对象,要调用的方法,调用的方法需要传递的参数 // 代理对象要做的事情 if (method.getName().equals("sing")) { System.out.println("准备话筒,收钱20万"); // 代理要干的事情 // return method.invoke(bigStar, args); } else if(method.getName().equals("dance")) { System.out.println("准备场地,收钱1000万"); // return method.invoke(bigStar, args); } return method.invoke(bigStar, args); } }); // 产生一个代理对象 return starProxy; } }
主程序
public class Test {
public static void main(String[] args) {
BigStar s = new BigStar("杨");
Star starProxy = ProxyUtil.creatrProxy(s);
String rs = starProxy.sing("好日子");
System.out.println(rs);
starProxy.dance();
}
}
一些通用的功能可以通过代理在不修改原代码的情况下,为不同对象添加通用功能
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。