测试分类:
- 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值。
- 白盒测试:需要写代码的。关注程序具体的执行流程。
什么是单元测试
- 对一部分代码进行测试
加端端老师免费领取更多编程资料
Junit是一个Java语言的单元测试框架,属于白盒测试,简单理解为可以用于取代java的main方法。Junit属于第三方工具,需要导入jar包后使用。
什么是Junit:
- 是第三方写的一个单元测试框架,可以取代main方法
- Junit需要导入jar包,压缩包,里面有很多的java代码,因为Junit使用广泛,所以idea就已经包含了Junit,只需要引入即可
Junit的好处:
- 可以单独测试一部分代码
Junit的使用步骤:
> 编写测试类
>
> 编写测试方法:
>
> 必须是public修饰符的
>
> 必须是没有返回值的void
>
> 必须没有参数
>
> > public void 方法名() {
> > 测试代码
> > }
>
> 给测试方法添加@Test注解
>
> 运行测试方法
>
> 看结果
>
> 绿色:表示通过
> 红色:表示失败
- 编写测试类,简单理解Junit可以用于取代java的main方法
- 在测试类方法上添加注解 home.php?mod=space&uid=101628
- @Test修饰的方法要求:public void 方法名() {…} ,方法名自定义建议test开头,没有参数。
- 添加Junit库到lib文件夹中,然后进行jar包关联
- 使用:点击方法左侧绿色箭头,执行当前方法(方法必须标记@Test)。执行结果红色:代表失败;执行结果 绿色:代表成功
复制代码 隐藏代码 package com.mobai; import org.junit.Test; import java.util.Arrays; /** * Software:IntelliJ IDEA 2020.1 x64 * Author: MoBai·杰 * ClassName:Test * 类描述:Junit测试 */ public class TestDemo1 { @Test public void test01() { for (int i = 0; i < 100; i++) { System.out.println(" i: " + Arrays.class.getClass()); } } }
- @Test,用于修饰需要执行的测试方法
- @Before,修饰的方法会在测试方法之前被自动执行
- @After,修饰的方法会在测试方法执行之后自动被执行
复制代码 隐藏代码 package com.mobai; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.util.Arrays; /** * Software:IntelliJ IDEA 2020.1 x64 * Author: MoBai·杰 * ClassName:Test * 类描述:Junit测试 */ public class TestDemo1 { @Before public void testBefore() { System.out.println(" 前置方法 "); } @After public void testAfter() { System.out.println(" 后置方法 "); } @Test public void test01() { for (int i = 0; i < 10; i++) { System.out.println(" i: " + Arrays.class.getClass()); } } }
- 当程序需要用到Person类的时候会将Person.class加载到内存中
- 将Person.class加载到内存,分别存放成员变量,成员方法,构造方法
- Java虚拟机会主动创建一个Class对象,描述方法区中的Person.class的内容
> 什么是反射?
- 在程序运行的过程中,通过Class对象得到类中构造方法,成员方法,成员变量,并操作他们
> 反射的应用场景
- idea等开发工具的智能提示
- 开发框架 SSM
> 反射的好处
- 可以在程序运行过程中,操作这些对象。
- 可以解耦,提高程序的可扩展性。
获取CLASS对象的方式 | 作用 | 应用场景 |
---|---|---|
类名.class | 通过类名的属性class获取 | 多用来传递参数 |
Class.forName(“类全名”) | 通过指定的字符串路径获取 | 多用来加载配置文件,将类名定义在配置文件中,读取文件,加载类 |
对象.getClass() | 通过对象的getClass()方法获取 | 多用来获取对象的字节码 |
三种获取Class对象的方式
- 类名.class
- 对象名.getClass()
- Class.forName(类全名)/(类全名就是:包名.类名)
> 注意:这三种方式得到的都是同一个对象
复制代码 隐藏代码 /** * Software:IntelliJ IDEA 2020.1 x64 * Author: MoBai·杰 * ClassName:TestClass * 类描述: 三种获取Class对象的方式 */ public class TestClass { public static void main(String[] args) throws Exception { // 1.类名.class Class clz = Book.class; System.out.println("clz = " + clz); // 2.通过对象名.getClass() Book book = new Book(); Class clz2 = book.getClass(); System.out.println("clz2 = " + clz2); // 3.通过Class.forName(类全名) Class clz3 = Class.forName("com.mobai.annion.Book"); System.out.println("clz3 = " + clz3); // 这三种方式得到的都是同一个对象 System.out.println(clz2 == clz3); System.out.println(clz == clz2); } }
加端端老师免费领取更多编程资料
常用方法:
String getSimpleName(); | 获得简单类名,只是类名,没有包 |
---|---|
String getName(); | 获得完整类名,包含包名 + 类名 |
T newTnstatance(); | 创建此Class对象所表示的类是一个新实例<br />要求:类必须有<public>的无参构造方法 |
复制代码 隐藏代码 public class Test02 { public static void main(String[] args) throws ClassNotFoundException { // 1.得到Class对象 Class clazz = Class.forName("com.mobai.annion.Book"); // 2.调用方法getName String name1 = clazz.getName(); // name1 = com.mobai.annion.Book System.out.println("name1 = " + name1); // 2.1调用方法getSimpleName String name2 = clazz.getSimpleName(); // name2 = Book System.out.println("name2 = " + name2); } }
Constructor类作用:
- 表示类中构造方法
如何得到public的Constructor对象:
- 获取Class对象
- 通过Class对象获取构造方法
> cls.getConstructor(); 获取一个public的构造方法
>
> cls.getConstructors(); 获取所有public的构造方法
Constructor类的方法:
- newInstance(); 创建对象
基本数据类型与引用数据类型的Class对象
> int.class != Integer.class
复制代码 隐藏代码 /** * Software:IntelliJ IDEA 2020.1 x64 * Author: MoBai·杰 * ClassName:Student * 类描述: 学生类 */ public class Student { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Student(String name) { this.name = name; } public Student(Integer age) { this.age = age; } public Student(String name, Integer age) { this.name = name; this.age = age; } public Student() { } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
复制代码 隐藏代码 public class TestDemo1 { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.mobai.fanshe.Student"); // 1.获取所有public的构造方法 Constructor<?>[] constructors = clazz.getConstructors(); for (Constructor<?> constructor : constructors) { System.out.println("constructor = " + constructor); } // 2.获取一个public构造方法 Constructor<?> constructors1 = clazz.getConstructor(); // public com.mobai.fanshe.Student() System.out.println("constructors1 = " + constructors1); // 2.1反射获取指定的构造方法 Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class); // public com.mobai.fanshe.Student(java.lang.String,java.lang.Integer) System.out.println("constructor = " + constructor); } }
复制代码 隐藏代码 public class TestDemo1 { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.mobai.fanshe.Student"); // 1.获取所有public的构造方法 Constructor<?>[] constructors = clazz.getConstructors(); for (Constructor<?> constructor : constructors) { System.out.println("constructor = " + constructor); } // 2.获取一个public构造方法 Constructor<?> constructors1 = clazz.getConstructor(); // public com.mobai.fanshe.Student() System.out.println("constructors1 = " + constructors1); // 2.1反射获取指定的构造方法 Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class); // public com.mobai.fanshe.Student(java.lang.String,java.lang.Integer) System.out.println("constructor = " + constructor); // 3.使用newInstance创建对象 Object instance = constructor.newInstance("墨白君", 15); // Student{name='墨白君', age=15} System.out.println("instance = " + instance); } }
声明的Constructor就是类中有的构造方法,不管权限
如何得到声明的Constructor:
- 得到Class对象
- 通过Class对象得到声明Constructor
> Declared的规律:
>
> cls.getConstructor(); 获取一个public的构造方法
> cls.getConstructors(); 获取所有public的构造方法
> cls.getDeclaredConstructors(); 得到所有声明的构造方法
> cls.getDeclaredConstructor(); 得到一个声明的构造方法
> 没有Declared是得到public的
> 有Declared是得到声明的
> 没有s的是得到一个
> 有s的是得到多个对私有构造方法我们在使用之前调用
- con.setAccessible(true); 暴力反射
复制代码 隐藏代码 public class Student { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Student(String name) { this.name = name; } private Student(Integer age) { this.age = age; } public Student(String name, Integer age) { this.name = name; this.age = age; } public Student() { } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
复制代码 隐藏代码 public class TestDemo2 { public static void main(String[] args) throws Exception { // 1.获取Class对象 Class<?> clazz = Class.forName("com.mobai.fanshe.Student"); // 2.得到一个申明的构造方法 Constructor<?> constructor = clazz.getDeclaredConstructor(Integer.class); // private com.mobai.fanshe.Student(java.lang.Integer) System.out.println("constructor = " + constructor); // 暴力反射 constructor.setAccessible(true); // 创建对象 Object instance = constructor.newInstance(16); System.out.println("instance = " + instance); } }
Class的newInstance方法就是使用无参构造创建对象.
复制代码 隐藏代码 public class TestDemo3 { public static void main(String[] args) throws Exception { // 获取Class对象 Class<?> clazz = Class.forName("com.mobai.fanshe.Student"); // 获取无参构造 Constructor<?> constructor = clazz.getConstructor(); // 通过无参构造创建对象 Object instance = constructor.newInstance(); // instance = Student{name='null', age=null} System.out.println("instance = " + instance); // Class对象创建对象的方法 Student instance1 = (Student) clazz.newInstance(); // instance1 = Student{name='null', age=null} System.out.println("instance1 = " + instance1); } }
Method类作用
- 表示类中的方法
如何得到Method对象
- 得到Class对象
- 通过Class对象获取Method
- cls.getMethods(); 获取所有public的方法
- cls.getMethod(); 获取一个public的方法
- cls.getDeclaredMethods(); 获取所有声明的方法
- cls.getDeclaredMethod(); 获取一个声明的方法
Method类中的方法: 得到Method就可以调用这个方法
- Object invoke(Object target, Object... args);
- Object target: 调用方法的对象
- Object... args: 调用方法时传递的参数
- Object: 返回值类型
复制代码 隐藏代码 public class Student { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Student(String name) { this.name = name; } private Student(Integer age) { this.age = age; } public Student(String name, Integer age) { this.name = name; this.age = age; } public Student() { } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
复制代码 隐藏代码 public class TestDemo4 { public static void main(String[] args) throws Exception { // 获取Class对象 Class<?> clazz = Class.forName("com.mobai.fanshe.Student"); // 通过CLass获取方法 Method[] methods = clazz.getMethods(); // 遍历获取所有public方法 for (Method method : methods) { System.out.println("method = " + method); } // 获取一个方法 Method setName = clazz.getMethod("setName", String.class); // setName = public void com.mobai.fanshe.Student.setName(java.lang.String) System.out.println("setName = " + setName); // 获取所有声明的方法 Method[] methods1 = clazz.getDeclaredMethods(); for (Method method : methods1) { System.out.println("method = " + method); } // 获取一个声明的方法 Method getName = clazz.getDeclaredMethod("getName"); // public java.lang.String com.mobai.fanshe.Student.getName() System.out.println("getName = " + getName); } }
加端端老师免费领取更多编程资料
> 注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、 接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
Annotnation的作用:
- 说明程序的,给计算机解释
- 可以被其他程序读取
Annotnation的格式
- 注解是以"@注解名称"在代码中存在的,还可以添加一些参数
Annotnation在哪里使用?
- 可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,可以通过反射机制编程实现对这些元数据的访问
作用分类:
- 编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
- 代码分析:通过代码里标识的注解对代码进行分析【使用反射】
- 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
常见注解:
- @author:用来标识作者名,eclipse开发工具默认的是系统用户名。
- @since: 从那个版本开始
- @version:用于标识对象的版本号,适用范围:文件、类、方法。
- @Override:用来修饰方法声明,告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败。
自定义注解: 注解本质上就是一个接口,该接口默认继承Annotation接口
复制代码 隐藏代码 public interface MyAnno extends java.lang.annotation.Annotation {}
复制代码 隐藏代码 // 空注解 public @interface Anno01 { }
只能使用Java提供的基本数据类型,String可以,Class可以,枚举类,其他暂未测试,包装类不可以.自定义类不可以
复制代码 隐藏代码 public @interface Anno02 { // 属性 String name(); double price() default 99; String[] authors(); // Anno01 abc(); // 注解 // WeekDay w(); // Class p(); } enum WeekDay { SUN, MON } class Person { }
- 八种基本数据类型
- String,注解,枚举,Class
- 以上类型的一维数组
> 自定义类不可以
注解可以用来保存数据
使用自定义注解格式:
> @注解名(属性名=属性值, 属性名=属性值)
注意:注解的属性可以有默认值,当使用注解时不赋值就使用默认值,赋值就按照赋的值
复制代码 隐藏代码 package com.mobai.annaction; // 自定义注解 public @interface MoBai { // 名字 String name(); // 默认属性 String value() default "框架师"; }
复制代码 隐藏代码 public class AnnactionTest { @MoBai(name = "墨白",value = "") public static void main(String[] args) { } @Test public void annTest(){ } }
当注解只有一个属性,并且属性名是value时,在使用注解时可以省略属性名
复制代码 隐藏代码 public @interface MoBai { String value(); }
复制代码 隐藏代码 @MoBai("abc") public class Demo11 { @MoBai(value = "abc") public static void main(String[] args) { } }
- @Target
- @Retention
> 修饰注解的注解叫做元注解
@Target元注解:
默认情况注解可以放在任意位置
> 限制注解可以放在哪些位置
> @Target(ElementType.TYPE) 注解只能放在类或者接口上
> @Target(ElementType.CONSTRUCTOR) 注解只能放在构造方法上
> @Target(ElementType.FIELD) 注解只能放在成员变量上
> @Target(ElementType.METHOD) 注解只能放在成员方法上
> @Target(ElementType.LOCAL_VARIABLE) 注解只能放在局部变量上
@Retention元注解:
- 默认是CLASS阶段
> 限制注解可以活到什么时候
>
> > SOURCE = = = = = = = = = = >>CLASS = = = = = = = = = = = = = >>RUNTIME
> > * 源代码阶段(.java) = = = = >>编译 = = = >>.class = = = = = = >>运行
复制代码 隐藏代码 //@Target(ElementType.TYPE) // 注解只能放在类或者接口上 //@Target(ElementType.CONSTRUCTOR) // 注解只能放在构造方法上 //@Target(ElementType.FIELD) // 注解只能放在成员变量上 //@Target(ElementType.METHOD) // 注解只能放在成员方法上 //@Target(ElementType.LOCAL_VARIABLE) // 注解只能放在局部变量上 @Retention(RetentionPolicy.RUNTIME) public @interface MoBai { }
复制代码 隐藏代码 @MoBai public class Demo12 { @MoBai private String a; @MoBai public Demo12() { } @MoBai public static void main(String[] args) { @MoBai int x = 10; } }
- 什么是注解解析?
> 获取注解中保存的数据
- 注解解析相关接口?
> AnnotatedElement接口中:
>
> Annotation getAnnotation(Class<T> annotationClass) 获取一个注解
>
> Annotation[] getAnnotations() 获取多个注解
>
> boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 判断有没有指定的注解
>
> > 注意: Constructor , Field , Method实现了AnnotatedElement接口
- 如何解析注解?
> 注解在谁头上,就用谁来获取注解
> 注解在构造方法上,使用Constructor对象获取注解
> 注解在成员方法上,使用Method对象获取注解
> 注解在成员变量上,使用Field对象获取注解
> * 使用反射
复制代码 隐藏代码 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Software:IntelliJ IDEA 2020.1 x64 * Author: MoBai·杰 * [@]Interface:MoBook * 注解描述: 自定义注解 */ // 限定方法使用 @Target(ElementType.METHOD) // 活到运行时候 @Retention(RetentionPolicy.RUNTIME) public @interface MoBook { String name(); double price(); String[] authors(); }
复制代码 隐藏代码 /** * Software:IntelliJ IDEA 2020.1 x64 * Author: MoBai·杰 * ClassName:Book * 类描述: 书籍类 */ public class Book { @MoBook(name = "框架师", price = 25.0, authors = "墨白") public void sell() { } }
复制代码 隐藏代码 public class TestMoBook { public static void main(String[] args) throws Exception { // 1.获取Class对象 Class<?> className = Class.forName("com.mobai.annion.Book"); // 2.获取Method对象 Method method = className.getMethod("sell"); // 3.通过method对象获取注解 Annotation[] annotations = method.getAnnotations(); // 4.遍历数组 for (Annotation annotation : annotations) { System.out.println("annotation = " + annotation); } // 3.3 boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) // 判断有没有指定的注解 boolean b = method.isAnnotationPresent(MoBook.class); System.out.println(b); if (b) { // 3.2 Annotation getAnnotation(Class<T> annotationClass) 获取一个注解 MoBook ann = method.getAnnotation(MoBook.class); System.out.println(ann.name() + "::" + ann.price() + "::" + Arrays.toString(ann.authors())); } } }
加端端老师免费领取更多编程资料