知识模块
一.Junit单元测试
二.反射
三.枚举
一.Junit单元测试a.概述Junit是一种Java写的单元测试框架,专门用来测试Java程序,它可以取代main方法b.Junit环境搭建由于Junit使用的类不属于我们JDK的类库,需要引入第三方jar包才能使用c.Junit使用/*Junit单元测试使用我们测试方法只需要在方法上添加一个注解 @Test1.我们在不同的方法上加上@Test,每个方法都可以独立运行2.如果在类上运行,那么会测试该类的所有方法,如果有一个方法测试失败,那么该类就测试失败各个方法 独立测试,相互不影响*/
import org.junit.Test;/*
Junit单元测试使用我们测试方法只需要在方法上添加一个注解 @Test1.我们在不同的方法上加上@Test,每个方法都可以独立运行2.如果在类上运行,那么会测试该类的所有方法,如果有一个方法测试失败,那么该类就测试失败各个方法 独立测试,相互不影响*/
public class JunitDemo01 {/* public static void main(String[] args) {int[] arr = {3, 5, 7,};for (int i : arr) {System.out.println(i);}*/@Testpublic void method01() {int[] arr = {3, 5, 7,};for (int i : arr) {System.out.println(i);}}@Testpublic void method02() {System.out.println(1 / 0);}@Testpublic void method03() {int[] arr = {3, 7, 5,};int sum=0;for (int i : arr) {sum += i;}System.out.println(sum);}
}
d.Junit注意事项/*Junit注意事项:@Test 只能用在基于一下模板定义的方法public void 方法名(){}1.权限修饰符必须是public2.返回值类型必须为void3.形参列表必须为空4.该方法不能是静态方法*/
import org.junit.Test;/*
Junit注意事项:@Test 只能用在基于一下模板定义的方法public void 方法名(){}1.权限修饰符必须是public2.返回值类型必须为void3.形参列表必须为空4.该方法不能是静态方法*/
public class JunitDemo02 {@Testprivate void method01() {System.out.println("私有方法");}@Testpublic int method02() {return 3;}@Testpublic void method03(int i) {System.out.println(i);}@Testprivate static void method04() {System.out.println("私有方法");}}
/*调用非public void method(){}的方法解决方案:先定义一个可以使用2Test注解方法,然后去调用不能使用@Test注解方法来达到测试目的*/
import org.junit.Test;/*
调用非public void method(){}的方法解决方案:先定义一个可以使用2Test注解方法,然后去调用不能使用@Test注解方法来达到测试目的*/
public class JunitDemo03 {@Testpublic void testMethod01() {//System.out.println("abc");method01();System.out.println(method02());}@Testpublic void testMethod02() {method03(15);}@Testpublic void testMethod03() {JunitDemo03.method04();method04();}private void method01() {System.out.println("私有方法");}public int method02() {return 3;}public void method03(int i) {System.out.println(i);}private static void method04() {System.out.println("静态方法");}
}
二.反射a.字节码对象当JVM用到一个类的时候,会把这个类加载到内存中,首先在方法区存放类的定义信息还要再堆内存中创建一个字节码对象和类文件(字节码文件)一一对应b.class类参见图解c.反射(reflect)概述反射其实就是解剖一个类,获取类中的各项信息(构造方法,成员变量,成员方法)类比:法医解剖人的尸体,人体内有很多器官(心肝脾肺肾),法医获取这些器官程序员解剖一个类,类中有构造方法信息,成员变量信息,成员方法信息,程序员获取这些信息d.获取字节码对象三种方式/*反射第一步获取字节码对象,因为只有获取到字节码对象,才能进一步获取类中的信息三种方式:1.类名.class 代表一个字节码对象2.通过Class类的方法,所以字节码对象都是Class类的实例static Class<?> forName(String className)返回与带有给定字符串名的类或接口相关联的 Class 对象。3.通过Object类中的getClass()方法获取该类的字节码对象Class<?> getClass()返回此 Object 的运行时类。无论采用哪种方式获取该类的字节码对象,都是获取了同一个字节码对象*/
/*
解剖Person类*/
public class Person {public String name;int age=13;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}private Person(String name) {this.name = name;}public void sleep() {System.out.println("只有睡得好,精神才能好");}public String eat(String food) {System.out.println("人吃" + food);return food;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}
import org.junit.Test;/*
反射第一步获取字节码对象,因为只有获取到字节码对象,才能进一步获取类中的信息三种方式:1.类名.class 代表一个字节码对象2.通过Class类的方法,所以字节码对象都是Class类的实例static Class<?> forName(String className)返回与带有给定字符串名的类或接口相关联的 Class 对象。3.通过Object类中的getClass()方法获取该类的字节码对象Class<?> getClass()返回此 Object 的运行时类。无论采用哪种方式获取该类的字节码对象,都是获取了同一个字节码对象*/
public class ReflectDemo01 {@Testpublic void testMethod01() {System.out.println(Person.class);//class reflect01.Person}@Testpublic void testMethod02() throws ClassNotFoundException {/*Class p = Class.forName("Perosn");System.out.println(p);*/Class p = Class.forName("reflect01.Person");System.out.println(p);//class reflect01.Person}@Testpublic void testMethod03() {Person p = new Person();System.out.println(p.getClass());//class reflect01.Person}@Testpublic void testMethod() throws ClassNotFoundException {Class p1 = Person.class;Class p2 = Class.forName("reflect01.Person");Class p3 = new Person().getClass();System.out.println(p1 == p2);//trueSystem.out.println(p2 == p3);//trueSystem.out.println(p1 == p3);//true}
}
e.反射构造方法/*反射(解剖出)构造方法Class<T>:T代表字节码对象所表示得类基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。只需要将基本类型后面加上.class就表示Class的实例Class类中的成员方法Constructor<T> getConstructor(Class<?>... parameterTypes)返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公有(public)构造方法。<T>:T代表字节码对象所表示得类Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)获取类中声明的任意一个构造方法T newInstance()只能利用该类的空参构造对象,不能利用有参创建对象Constructor类中的方法String getName()以字符串形式返回此构造方法的名称。T newInstance(Object... initargs)使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。*/
import org.junit.Test;
import reflect01.Person;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;/*
反射(解剖出)构造方法
Class<T>:T代表字节码对象所表示得类
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
只需要将基本类型后面加上.class就表示Class的实例Class类中的成员方法Constructor<T> getConstructor(Class<?>... parameterTypes)返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公有(public)构造方法。<T>:T代表字节码对象所表示得类Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)获取类中声明的任意一个构造方法T newInstance()只能利用该类的空参构造对象,不能利用有参创建对象Constructor类中的方法String getName()以字符串形式返回此构造方法的名称。T newInstance(Object... initargs)使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。*/
public class ReflectDemo01 {@Testpublic void testMethod01() throws Exception{//1.获取字节码对象Class<Person> pCLs = Person.class;//2.获取构造方法Constructor<Person> cons = pCLs.getConstructor();//由于获取的是空参构造,所以不需要传递任何参数,因此使用getConstructor()方法也不用传递参数//3.获取构造方法的信息System.out.println(cons.getName());//获取构造方法的名称 reflect01.Person//4.利用构造方法创建对象Person p = cons.newInstance();//利用空参构造创建对象//类比:Person p = new Perosn();System.out.println(p);//reflect01.Person@f5f2bb7}@Testpublic void testMethod02() throws Exception{//1.获取字节码对象Class<Person> pCLs = Person.class;//2.直接利用Class类的newInstance()方法创建该类实例Person p = pCLs.newInstance();System.out.println(p); //reflect01.Person@f5f2bb7}@Testpublic void testMethod() throws Exception{//1.获取字节码对象并获取有参构造Constructor<Person> cons = Person.class.getConstructor(String.class, int.class);//获取指定形参为String,int的方法//2.利用这个有参构造创建对象Person p = cons.newInstance("老王", 30);//类比:Perosn p = new Person("老王",30);System.out.println(p);}/*** 暴力反射:获取类中的一些私有属性* @throws Exception*/@Testpublic void testMethod04() throws Exception {//1.获取字节码对象Class<Person> pCLs = Person.class;//2.获取构造方法//Constructor<Person> cons = pCLs.getConstructor(String.class);Constructor<Person> cons = pCLs.getDeclaredConstructor(String.class);//2.5由于是将要利用私有构造方法创建对象,在类外无法调用私有构造方法,但是我们可以让java取消权限检查cons.setAccessible(true);//3.构造方法创建对象Person p = cons.newInstance("老李");//类似:Person p = new Person("老李");System.out.println(p);}
}
f.反射成员变量(字段)/*** 反射(解剖出)字段* Class类中的成员方法* Field getField(String name)* 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共public成员字段。** Field getDeclaredField(String name)* 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。** Field类中的成员方法* Object get(Object obj)* 返回指定对象上此 Field 表示的字段的值。*/
import org.junit.Test;
import reflect01.Person;import java.lang.reflect.Field;/** 反射(解剖出)字段* Class类中的成员方法* Field getField(String name)* 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共public成员字段。** Field getDeclaredField(String name)* 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。** Field类中的成员方法* Object get(Object obj)* 返回指定对象上此 Field 表示的字段的值。*/
public class ReflectDemo02 {@Testpublic void testMethod01() throws Exception {//1.获取Person类的字节码对象Class<Person> pCLs = (Class<Person>) Class.forName("reflect01.Person");//2.获取字段信息Field f = pCLs.getField("name");//System.out.println(f); //public java.lang.String reflect01.Person.name//3.获取该字段的值Person p = pCLs.newInstance(); //相当于Person p = new Person();System.out.println(f.get(p)); //由于成员对象随着对象的存在二存在,所以必须指定获取哪个对象的成员变量的值}@Testpublic void testMethod02() throws Exception {//1.获取Person类的字节码对象Class<Person> pCLs = (Class<Person>) Class.forName("reflect01.Person");//2.利用getDeclarField方法获取非public修饰的字段Field f = pCLs.getDeclaredField("age");//2.5通过setAccessiable设置Java的访问权限检查f.setAccessible(true);//3.获取当前field字段的值Person p = pCLs.newInstance();//相当于Person p = new Person();System.out.println(f.get(p));//13//4.设置当前field字段的值f.set(p, 28);//5.获取当前field字段的值System.out.println(f.get(p));//28}
}
g.反射成员方法/** 反射(解剖出)成员方法信息** Class类中的成员方法* Method getMethod(String name, Class<?>... parameterTypes)* 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。**Method类的方法:* Object invoke(Object obj, Object... args)* 形参:* Object obj:代表该类的一个对象* orgs:代表传递给方法的实参* 返回值:* 代表调用的方法的返回值* 如果该方法没有返回值,invoke()返回null*/
import org.junit.Test;
import reflect01.Person;import java.lang.reflect.Method;/** 反射(解剖出)成员方法信息** Class类中的成员方法* Method getMethod(String name, Class<?>... parameterTypes)* 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。**Method类的方法:* Object invoke(Object obj, Object... args)* 形参:* Object obj:代表该类的一个对象* orgs:代表传递给方法的实参* 返回值:* 代表调用的方法的返回值* 如果该方法没有返回值,invoke()返回null*/
public class ReflectDemo03 {@Testpublic void testMethod01() throws Exception {//1.获取字节码对象Class<Person> pCLs = (Class<Person>) Class.forName("reflect01.Person");//2.获取指定的成员方法Method sleepMethod = pCLs.getMethod("sleep");//3.通过invoke来调用该方法Person p = pCLs.newInstance();System.out.println(sleepMethod.invoke(p));//类似: Person p = new Person();// p.sleep();}@Testpublic void testMethod02() throws Exception {//1.获取字节码对象Class<Person> pCLs = (Class<Person>) Class.forName("reflect01.Person");//2.获取eat方法Method eatMethod = pCLs.getMethod("eat", String.class);//3.调用eat方法Person p = pCLs.newInstance();Object returnVal = eatMethod.invoke(p, "榴莲");//相当于:Person p = new Person();//String food = p.eat("蛋糕");//Ststem.out.println(food);System.out.println(returnVal);}}
三.枚举a.枚举概述一一列举如果某些变量的取值是固定几个值中其中一个,我们就考虑定义枚举星期(一~日) 月份(1~12) 性别(男/女)b.模拟java中的枚举/**一周(星期一~星期日)* 1.我们为一周每天定义一个Week对象,每个Week对象都代表改天**/public class Week {/**私有化构造方法目的:只能使用Week类中的这七个对象* 而不能在类外在创建该类对象*/private Week() {}private String weekName;//代表星期的名称private Week(String weekName) {this.weekName=weekName;}/**public: 保证权限足够大,在类外以及不同的包下都能访问*static: 不需要再类外创建对象,可以用过类名直接调用* final: final修饰变量,该变量只能被赋值一次,该变量就成为了常量* 常量的命名规范:变量名纯大写 XXX_XXX_XXX*//* public static final Week MONDAY = new Week();public static final Week TUESDAY = new Week();public static final Week WEDNESDAY = new Week();public static final Week THURSDAY = new Week();public static final Week FRIDAY = new Week();public static final Week SATURDAY = new Week();public static final Week SUNDAY = new Week();*/public static final Week MONDAY = new Week("星期一");public static final Week TUESDAY = new Week("星期二");public static final Week WEDNESDAY = new Week("星期三");public static final Week THURSDAY = new Week("星期四");public static final Week FRIDAY = new Week("星期五");public static final Week SATURDAY = new Week("星期六");public static final Week SUNDAY = new Week("星期日");@Overridepublic String toString() {return weekName;}}
import org.junit.Test;public class WeekDemo {@Testpublic void testMethod01() {//Week week = new Week();//Week.monday=null;System.out.println(Week.MONDAY);System.out.println(Week.FRIDAY);}
}
/**一周(星期一~星期日)* 1.我们为一周每天定义一个Week对象,每个Week对象都代表改天**/
public class Week {/**私有化构造方法目的:只能使用Week类中的这七个对象* 而不能在类外在创建该类对象*/private Week() {}private String weekName;//代表星期的名称private Week(String weekName) {this.weekName=weekName;}/**public: 保证权限足够大,在类外以及不同的包下都能访问*static: 不需要再类外创建对象,可以用过类名直接调用* final: final修饰变量,该变量只能被赋值一次,该变量就成为了常量* 常量的命名规范:变量名纯大写 XXX_XXX_XXX*//* public static final Week MONDAY = new Week();public static final Week TUESDAY = new Week();public static final Week WEDNESDAY = new Week();public static final Week THURSDAY = new Week();public static final Week FRIDAY = new Week();public static final Week SATURDAY = new Week();public static final Week SUNDAY = new Week();*/public static final Week MONDAY = new Week("星期一");public static final Week TUESDAY = new Week("星期二");public static final Week WEDNESDAY = new Week("星期三");public static final Week THURSDAY = new Week("星期四");public static final Week FRIDAY = new Week("星期五");public static final Week SATURDAY = new Week("星期六");public static final Week SUNDAY = new Week("星期日");@Overridepublic String toString() {return weekName;}
}
c.利用enum创建枚举/** Java中利用enum关键字定义枚举* 格式:* 权限修饰符 enum 枚举名称{* 枚举变量1,枚举变量2,枚举变量3....;* }** JAVA中利用enum定义的枚举和我们自己模拟的枚举原理相同*/public enum Week {MONDAY("星期一"),THESDAY("星期二"),WEDNESDAY("星期三"),THURSDAY("星期四"),FRIDAY("星期五"),SATURDAY("星期六"),SUNDAY("星期日");private String weekName;private Week(String weekName) {this.weekName=weekName;}private Week() {}@Overridepublic String toString() {return weekName;}}
/** Java中利用enum关键字定义枚举* 格式:* 权限修饰符 enum 枚举名称{* 枚举变量1,枚举变量2,枚举变量3....;* }** JAVA中利用enum定义的枚举和我们自己模拟的枚举原理相同*/
public enum Week {MONDAY,THESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
}
import org.junit.Test;public class WeekDemo {@Testpublic void testMethod() {//Week week = new Week();System.out.println(Week.MONDAY);System.out.println(Week.FRIDAY);System.out.println(Week.MONDAY.getClass());//class enum03.Week}
}
d.枚举中常用的方法/**枚举中的常用方法* Java中所有用enum定义的枚举默认会继承一个类:java.lang.Enum** Class类中的方法* Class<? super T> getSuperclass()* 获取该字节码对象的父类字节码对象** Method[] getMethods()* 获取该字节码对象中所有public修饰的成员方法** 枚举中的常用方法:* public static Week[] values()* 获取所有的枚举常量,并把所有的枚举常量封装到一个数组中返回* public static Week.valueOf(String str)* public final String name() 返回此枚举常量的名称,在其枚举声明中对其进行声明。**/
/** Java中利用enum关键字定义枚举* 格式:* 权限修饰符 enum 枚举名称{* 枚举变量1,枚举变量2,枚举变量3....;* }** JAVA中利用enum定义的枚举和我们自己模拟的枚举原理相同*/
public enum Week {MONDAY,THESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
}
import org.junit.Test;import java.lang.reflect.Method;/**枚举中的常用方法* Java中所有用enum定义的枚举默认会继承一个类:java.lang.Enum** Class类中的方法* Class<? super T> getSuperclass()* 获取该字节码对象的父类字节码对象** Method[] getMethods()* 获取该字节码对象中所有public修饰的成员方法** 枚举中的常用方法:* public static Week[] values()* 获取所有的枚举常量,并把所有的枚举常量封装到一个数组中返回* public static Week.valueOf(String str)* public final String name() 返回此枚举常量的名称,在其枚举声明中对其进行声明。**/
public class WeekDemo {@Testpublic void testMethod() {System.out.println(Week.class.getSuperclass());//class java.lang.Enum}@Testpublic void testMethod02() {//1.利用字节码对象获取所有的成员方法Method[] methods = Week.class.getMethods();//2.遍历methods数组for (Method method : methods) {System.out.println(method);}}@Testpublic void testMethod03() {Week[] weeks = Week.values();for (Week week : weeks) {System.out.println(week);}}@Testpublic void testMethod04() {System.out.println(Week.valueOf("MONDAY"));System.out.println(Week.valueOf("MONDAY")==Week.MONDAY);//true}@Testpublic void testMethod05() {System.out.println(Week.FRIDAY.name());//跟toString原理相同System.out.println(Week.FRIDAY);System.out.println(Week.FRIDAY.toString());}
}