枚举
jdk1.5之前,需要自己实现枚举
自己实现枚举
public class StatusEnum {
private final String id;
private final String code;
private final String name;
private StatusEnum(String id, String code, String name){
this.id = id;
this.code = code;
this.name = name;
}
public static final StatusEnum TODO = new StatusEnum("1","todo","待完成");
public static final StatusEnum DONE = new StatusEnum("2","todo","已完成");
public static final StatusEnum DOING = new StatusEnum("3","doing","正在完成");
public String getId() {
return id;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "StatusEnum{" +
"id='" + id + '\'' +
", code='" + code + '\'' +
", name='" + name + '\'' +
'}';
}
}
jdk1.5之后,提供了枚举
jdk提供的枚举
public enum StatusEnum2 {
TODO("1","todo","待完成"),
DONE("2","todo","已完成"),
DOING("3","doing","正在完成");
private final String id;
private final String code;
private final String name;
StatusEnum2(String id, String code, String name) {
this.id = id;
this.code = code;
this.name = name;
}
public String getId() {
return id;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
}
枚举的父类是java.lang.Enum
没有属性的枚举
public enum StatusEnum3 {
TODO,
DONE,
DOING;
}
枚举类常用的方法
toString(): 返回对象名
values:静态方法,获取所有对象名
valueOf(name): 根据name或者对象
StatusEnum3 doing = StatusEnum3.DOING;
System.out.println(doing.toString());
StatusEnum3[] values = StatusEnum3.values();
for(StatusEnum3 statusEnum3: values){
System.out.println(statusEnum3.toString());
}
StatusEnum3 done = StatusEnum3.valueOf("DONE");
System.out.println(done.toString());
枚举类也可以实现接口
接口
public interface TestInterface {
void show();
}
枚举类
public enum StatusEnum3 implements TestInterface{
TODO,
DONE,
DOING;
@Override
public void show() {
System.out.println("xxx");
}
}
此时,枚举对象调用接口方法时,调用的是同一个方法。
如果想要每种类型的枚举调用不同的方法实现,可以这样做:
public enum StatusEnum3 implements TestInterface{
TODO{
@Override
public void show() {
// todo something
}
},
DONE{
@Override
public void show() {
// todo something
}
},
DOING{
@Override
public void show() {
// todo something
}
};
}
枚举搭配switch case使用
case中不用写StatusEnum3.TODO,直接写TODO就可以了
StatusEnum3 statusEnum3 = StatusEnum3.DOING;
switch (statusEnum3){
case TODO: // do something
break;
case DOING: // do something
break;
case DONE: // do something
break;
}
反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。
获取字节码信息的四种方式
1. 通过对象获取
2. 通过内置class获取
3.通过forName获取
4.通过类加载器获取
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
// 通过对象获取
Person person = new Person();
Class<? extends Person> personClass = person.getClass();
// 通过内置class获取
Class<Person> personClass2 = Person.class;
// 通过Class.forName获取
Class<?> personClass3 = Class.forName("com.xy.shirotest.reflectTest.Person");
// 通过类加载器获取
Class<?> personClass4= Test.class.getClassLoader()
.loadClass("com.xy.shirotest.reflectTest.Person");
}
}
获取的所有字节码都是同一个。一个类只有一个字节码信息
Class类的具体实例
1. 类
2. 接口
3. 数组
4. 基本数据类型
5. 注解
6. void
// 可以作为Class类的实例
// 类
Class<Object> objectClass = Object.class;
// 接口
Class<Serializable> serializableClass = Serializable.class;
// 数组
int[] a = {1,2,3};
// 同一维度,同一个类型的字节码文件一样
Class<? extends int[]> aClass = a.getClass();
// 基本数据类型
Class<Integer> integerClass = int.class;
// 注解
Class<Controller> controllerClass = Controller.class;
// void
Class<Void> voidClass = void.class;
获取构造器
// 根据字节码获取构造器
// 获取字节码
Class<Object> clazz = Object.class;
// 获取public类型的所有构造器
Constructor<?>[] publicConstructors = clazz.getConstructors();
// 获取public类型无参构造器
Constructor<Object> publicWucanConstructor = clazz.getConstructor();
// 获取public类型指定构造器(参数根据构造器的参数类型来设定)
Constructor<Object> publicConstructor = clazz.getConstructor(int.class, double.class);
// 获取所有访问修饰符的构造器
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
// 获取所有访问修饰符的无参构造器
Constructor<Object> wucanDeclaredConstructor = clazz.getDeclaredConstructor();
// 获取所有访问修饰符的指定构造器(参数根据构造器的参数类型来设定)
Constructor<Object> declaredConstructor = clazz.getDeclaredConstructor(int.class, double.class);
// 通过构造器创建对象
Object o1 = publicWucanConstructor.newInstance();
//
Object o2 = declaredConstructor.newInstance(1, 1.2);
获取属性、给属性设值
// 获取当前类和父类中,所有被public修饰的属性
Field[] fields = clazz.getFields();
// 获取当前类中所有属性
Field[] declaredFields = clazz.getDeclaredFields();
// 根据属性名获取属性public
Field gender = clazz.getField("gender");
// 获取属性具体信息 ---------------------
// 获取属性名
String name = gender.getName();
// 获取属性类型
String typeName = gender.getType().getName();
// 获取访问修饰符
String modifier = Modifier.toString(gender.getModifiers());
// 给属性设值
Object obj = clazz.newInstance();
gender.set(obj, "男");
获取方法
/* 获取方法 */
// 获取运行时类和所有父类的public方法
Method[] publicMethods = clazz.getMethods();
// 根据方法名获取不带参数的public方法(运行时类和所有父类的)
Method eat = clazz.getMethod("eat");
// 根据方法名和参数类型获取public方法(运行时类和所有父类的)
Method sleep = clazz.getMethod("sleep", int.class, long.class);
// 获取运行时类所有方法
Method[] declaredMethods = clazz.getDeclaredMethods();
// 根据方法名获取不带参数的方法
Method hello = clazz.getMethod("hello");
// 根据方法名和参数类型获取方法
Method world = clazz.getDeclaredMethod("world", String.class, double.class);
/* 获取方法相关参数 */
// 方法修饰符
String methodModifier = Modifier.toString(world.getModifiers());
// 方法返回值类型
Class<?> returnType = world.getReturnType();
// 方法名
String methodName = world.getName();
// 方法参数列表类型
Class<?>[] parameterTypes = world.getParameterTypes();
// 注解 只能获取RUNTIME类型的注解
Annotation[] annotations = world.getAnnotations();
/* 方法调用 */
Object o = clazz.newInstance();
Object invokeReturn = world.invoke(o, "zhangsan", 19.8);
获取其他信息
// 获取运行时class的接口
Class<?>[] interfaces = clazz.getInterfaces();
// 获取父类
Class<? super Object> superclass = clazz.getSuperclass();
// 获取父类接口
Class<?>[] superInterfaces = superclass.getInterfaces();
// 获取当前类的包
Package aPackage = clazz.getPackage();
// 获取当前类的注解
Annotation[] classAnnotations = clazz.getAnnotations();
测试
黑盒测试:不需要关注代码
白盒测试:需要关注代码
junit单元测试属于白盒测试