1、单元测试
-
什么是单元测试?单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此,单元测试就是针对Java方法的测试,进而检查方法的正确性。
-
目前测试方法是怎么进行的,存在什么问题?
-
只有一个main方法,如果一个方法的测试失败了,其他方法测试会受到影响
-
无法得到测试的结果报告,需要程序员自己去观察测试是否成功。
-
无法实现自动化测试。
-
-
Junit单元测试框架,JUnit是使用Java语言实现的单元测试框架,它是开源的,Java开发者都应当学习并使用JUnit编写单元测试。此外,几乎所有的IDE工具都集成了IUnit,这样我们就可以直接在IDE中编写并运行IUnit测试,JUnit目前最新版本是5。
-
JUnit优点
-
JUnit可以灵活的选择执行哪些测试方法,可以一键执行全部测试方法。
-
Junit可以生成全部方法的测试报告。
-
单元测试中的某个方法测试失败了,不会影响其他测试方法的测试。
-
-
Junit快速入门
-
需求:使用单元测试进行业务方法预期结果、正确性测试的快速入门
-
分析:
-
将Unit的iar包导入到项目中,IDEA通常整合好了Junit框架,一般不需要导入。如果IDEA没有整合好,需要自己手工导入如下2个IUnit的iar包到模块
-
编写测试方法:该测试方法必须是公共的无参数无返回值的非静态方法。
-
在测试方法上使用@Test注解,标注该方法是一个测试方法
-
在测试方法中完成被测试方法的预期正确性测试。选中测试方法,选择“JUnit运行”,如果测试良好则是绿色;如果测试失败,则是红色
-
-
使用示例:
//有待测试方法的类 public class TestDemo { //返回 1 + 2.....+100的值。 public int sum(){ int result = 0; for (int i = 0; i < 100; i++) { result += i; } return result; } //一个会出问题的方法。 public void div(){ System.out.println(5/0); } } //测试 public class Test { @org.junit.Test public void testSum(){ TestDemo demo = new TestDemo(); int sum = demo.sum(); //通常会使用Assert.assertEquals()方法来测试有返回值的方法。 //第一个参数表示返回值有误的提示信息。 //第二个参数表示期待的返回值 //第三个表示实际上返回的值。 Assert.assertEquals("返回值有误",5050,sum); } @org.junit.Test public void testDiv(){ TestDemo demo = new TestDemo(); demo.div(); } }
-
-
Junit常用方法
-
@Test:测试方法
-
@Before:用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次。
-
@After:用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次。
-
@BeforeClass:用来静态修饰方法,该方法会在所有测试方法之前只执行一次。
-
@AfterClass:用来静态修饰方法,该方法会在所有测试方法之后只执行一次。
-
开始执行的方法,用于初始化资源。执行完之后的方法,用于释放资源。
-
2、反射
-
反射概述
-
反射是指对于任何一个Class类,在"运行的时候"都可以直接得到这这个类全部成分。
-
反在运行时,可以直接得到这个类的构造器对象:Constructor
-
反在运行时,可以直接得到这个类的成员变量对象:Field
-
反在运行时,可以直接得到这个类的成员方法对象:Method
-
反这种运行时动态获取类信息以及动态调用类中成分的能力称为java语言的反射机制。
-
-
反射的关键:反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分。
-
获取反射类对象
-
获取反射类对象一般有三种方式
-
使用示例:三个打印结果都为class shh.People,也就是说一个类只有一个class对象。
public static void main(String[] args) throws Exception { //方式一:Class.forName(全类名),参数为包名.包名....类名,完整的类名 Class<?> class01 = Class.forName("shh.People"); System.out.println(class01); //方式二:类名.class Class<People> class02 = People.class; System.out.println(class02); //方式三:对象.getClass(),getClass()方法为老祖宗Object对象的方法。 People people = new People(); Class<? extends People> class03 = people.getClass(); System.out.println(class03); }
-
-
反射获取构造器对象
-
使用反射可以获取构造器对象
-
Class类中用于获取构造器的方法
-
Constructor<?>[] getConstructors():返回所有构造器对象的数组(只能拿public的)
-
Constructor<?>[] getDeclaredConstructors():返回所有构造器对象的数组,存在就能拿到
-
Constructor
getConstructor(Class<?>... parameterTypes):返回单个构造器对象(只能拿public的) -
Constructor
getDeclaredConstructor(Class<?>... parameterTypes):返回单个构造器对象,存在就能拿到
-
-
示例
public static void main(String[] args) throws Exception{ //获取People类的class对象。 Class<People> peopleClass = People.class; //getConstructors(),获取所有的构造器对象,private方法无法获取。 Constructor<?>[] constructors = peopleClass.getConstructors(); //getDeclaredConstructors(),获取所有的构造器对象,私有方法也可以获取到。 Constructor<?>[] declaredConstructors = peopleClass.getDeclaredConstructors(); //getConstructor(类型.class),获取指定参数类型的一个构造器。私有方法无法获取 Constructor<People> constructor = peopleClass.getConstructor(String.class); //getDeclaredConstructor(类型.class),获取指定参数类型的一个构造器,私有方法也可以获取到, Constructor<People> declaredConstructor = peopleClass.getDeclaredConstructor(String.class); }
-
-
使用构造器对象创建类对象
-
Constructor类中用于创建对象的方法
-
T newlnstance(Object... initargs):根据指定的构造器创建对象
-
public void setAccessible(boolean flag):设置为true表示取消访问检查,进行暴力反射,也就是说私有构造器对象也可以创建对象。
-
-
示例
public class People { private String name; private int age; //私有构造器 private People(){} public People(String name) { this.name = name; } public People(String name, int age) { this.name = name; this.age = age; } } //测试 public static void main(String[] args) throws Exception{ //获取People类的class对象。 Class<People> peopleClass = People.class; //获取空参数的私有构造器 Constructor<People> privateConstructor = peopleClass.getDeclaredConstructor(); //People people = privateConstructor.newInstance(); 执行失败,私有构造器不能创建对象。 privateConstructor.setAccessible(true); //暴力反射,让私有构造器也可以创建对象 People people = privateConstructor.newInstance(); //执行成功 //获取两个参数的构造器 Constructor<People> constructor = peopleClass.getConstructor(String.class, Integer.class); People people1 = constructor.newInstance("小明", 10); }
-
-
反射获取成员变量对象
-
使用反射可以获取成员变量对象
-
获取成员变量对象的方法
-
Field getField(String name):根据成员变量名获得对应Field对象,只能获得public修饰的成员变量
-
FField getDeclaredField(String name):根据成员变量名获得对应Field对象,只要申明了就可以得到(可以获取任何访问权限的成员变量)
-
Field[] getFields():获得所有的成员变量对应的Field对象,只能获得public的成员变量
-
Field[] getDeclaredFields():获得所有的成员变量对应的Field对象,只要申明了就可以得到
-
-
Field类中操作成员变量的方法,给成员变量赋值和取值
-
void set(Object obj, object value):给对象注入某个成员变量数据
-
Object get(Object obj):获取对象的成员变量的值。
-
void setAccessible(true):暴力反射,设置为可以直接访问私有类型的属性。
-
Class getType0):获取属性的类型,返回Class对象。
-
String getName():获取属性的名称。
-
-
使用示例
public class People { private String name; public int age; public People(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } //测试 public static void main(String[] args) throws Exception{ //获取People类的class对象。 Class<People> peopleClass = People.class; //Field name = peopleClass.getField("name");//执行失败,getField不能获取私有成员变量 //使用getField()获取public修饰的成员变量。 Field age = peopleClass.getField("age"); //使用getDeclaredField()获取私有成员变量。 Field name = peopleClass.getDeclaredField("name"); //使用set()方法修改变量内容。 People people = new People("小明",10); //name.set(people,"小红"); 执行失败,私有的成员变量不允许修改变量内容 name.setAccessible(true); name.set(people,"小红"); //先使用setAccessible暴力反射,就可以修改变量内容了。 //获取某个对象的变量信息 Class<?> type = age.getType(); //获取变量类型 String name1 = age.getName(); //获取变量名 }
-
-
反射获取成员方法对象
-
使用反射可以获取成员方法对象
-
获取成员方法对象的方法
-
Method[] getMethods():返回所有成员方法对象的数组(只能拿public的)
-
Method[] getDeclaredMethods():返回所有成员方法对象的数组,存在就能拿到
-
Method getMethod(String name,Class<?>... parameterTypes):返回单个成员方法对象(只能拿public的)
-
Method getDeclaredMethod(String name,Class<?>... parameterTypes):返回单个成员方法对象,存在就能拿到
-
-
执行方法的方法:Object invoke(Object obj,Object... args)
-
参数一:用obj对象调用该方法,指定要调用方法的对象
-
参数二:调用方法的传递的参数(如果没有就不写)
-
返回值:方法的返回值(如果没有就不写)
-
-
使用示例
public class People { private String name; public People(String name) { this.name = name; } //一个公共的方法,会吃饭,无返回值 public void eat(String thing){ System.out.println(this.name + "会吃"+thing); } //一个私有的方法,返回名字 private String getName(){ return this.name; } } //测试 public static void main(String[] args) throws Exception { Class<People> p = People.class; //获取公共方法 Method eat = p.getMethod("eat",String.class); //getDeclaredMethod可以 获取私有方法。 //Method getName = p.getMethod("getName"); 执行失败,不能获取私有方法 Method getName = p.getDeclaredMethod("getName"); //invoke方法,用于执行某个对象的方法。 People people = new People("小明"); eat.invoke(people,"冰淇淋"); //String invoke = (String)getName.invoke(people); 执行失败,私有方法不可被执行 getName.setAccessible(true); //暴力反射之后,私有方法就可以被执行了 String invoke = (String)getName.invoke(people); System.out.println(invoke); }
-
-
反射的应用
-
反射的作用-绕过编译阶段为集合添加数据
-
反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素的。
-
泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList了,泛型相当于被擦除了。所以就可以使用反射,来为集合添加数据
-
演示
public static void main(String[] args) throws Exception { ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(2); //list.add("你好"); 编译报错 Class<? extends ArrayList> c = list.getClass(); //获取class对象 Method add = c.getMethod("add", Object.class); //获取add方法对象 add.invoke(list,"你好"); //执行成功 System.out.println(list); //输出:[1, 2, 你好] }
-
实际上有另一种方式可以突破泛型的约束
public static void main(String[] args) throws Exception { ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(2); //list.add("你好"); 编译报错 ArrayList list2 = list; //将list2指向list对象。 list2.add("你好"); //此时list2对象是没有被泛型约束的 System.out.println(list); //输出:[1, 2, 你好] }
-
-
反射的作用- 反射做通用框架
-
需求:给你任意一个对象,在不清楚对象字段的情况可以,可以把对象的字段名称和对应值存储到文
件中去。 -
分析
-
代码实现:
//使用反射获取对象信息并打印到文件上 public static void getMeg(Object obj){ PrintStream ps = null; try { //使用打印流,指定要打印到哪个文件中去。 ps = new PrintStream(new FileOutputStream("C:\\Users\\86158\\Desktop\\test.txt",trued)); Class<?> c = obj.getClass(); String className = c.getName(); //获取类名 ps.println("================="+className+"=============="); Field[] fields = c.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); String fieldName = field.getName(); Object value = field.get(obj); ps.println(fieldName + "="+value); } } catch (Exception e) { throw new RuntimeException(e); } finally { if(ps != null){ ps.close(); } } } // 测试 public static void main(String[] args) throws Exception { getMeg(new Teacher("小红",465)); getMeg(new Student("小明",45,'男',180,"王者荣耀")); }
结果:
-
-
3、注解
-
注解概述
-
Java注解(Annotation)又称Java标注,是JDK50引入的一种注释机制。Java 语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注。
-
注解的作用:对Java中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来决定。例如:JUnit框架中,标记了注解@Test的方法就可以被当成测试方法执行,而没有标记的就不能当成测试方法执行。
-
-
自定义注解
-
定义注解的基本形式:default 默认值 可以省略。
-
注意:
-
value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写!!但是如果有多个属性,且多个属性没有默认值,那么value名称是不能省略的。
-
default 默认值 可以省略。设置默认值之后的属性,在使用注解时,可以不为其赋值,直接使用默认值即可。若不设置默认值,则必须为其赋值,除了特殊属性value之外,赋值语句必须为“属性名=属性值”
-
-
自定义注解示例:
//自定义的注解 public @interface MyAnnotation { public String value(); //public 修饰符可以省略,因为默认就是public修饰 String name() default "shh"; //设置默认值之后,在使用注解时,可以省略该属性值的赋值过程 public int age() default 18; } //使用自定义注解 public class Main { //由于MyAnnotation注解中,除了value属性之外,其他的属性都有默认值 //所以此处可以省略 “value=” 以及 其他属性值赋值的语句。 @MyAnnotation("shh") public void aMethod01(){} //必须为所有属性值赋值,除非它有默认值。赋值语句必须为 “属性名=值”。 @MyAnnotation(value = "shh",name = "sfaf",age = 16) public void aMethod02(){} }
-
-
元注解
-
概述:元注解就是注解注解的注解,也就是对注解使用的注解。
-
元注解有两个:
-
@Target:约束自定义注解只能在哪些地方使用
-
@Retention:申明注解的生命周期
-
-
@Target中可使用的值定义在 ElementType枚举类中,常用值如下
-
TYPE,类,接口
-
FIELD 成员变量
-
METHOD 成员方法
-
PARAMETER 方法参数
-
CONSTRUCTOR 构造器
-
LOCAL VARIABLE 局部变量
-
-
@Retention中可使用的值定义在 RetentionPolicy 枚举类中,常用值如下
-
SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
-
CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值。
-
RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)
-
-
target使用示例
//定义了一个注解,使用target元注解标注它只能被用于方法和成员变量中。 @Target({ElementType.FIELD,ElementType.METHOD}) public @interface MyAnnotation { public String value(); } //测试 @Target({ElementType.FIELD,ElementType.METHOD}) //@MyAnnotation("shh") 报错,该注解不能注解类。 public class Main { //注解成员变量、方法都没有异常。 @MyAnnotation("shh") private String name; @MyAnnotation("shh") public void aMethod02(){} }
-
-
注解解析 (
标签:String,05,单元测试,class,注解,方法,public,name From: https://www.cnblogs.com/Chihuatanio/p/17314150.html