一、Junit单元测试
1.Junit介绍
概述:Junit是一个单元测试框架,可以代替main方法去执行其他的方法
作用:单独执行一个方法,测试该方法是否能跑通
注意:Junit是第三方工具,所以使用之前需要导入jar包
2.Junit的基本使用(重点)
导入Junit的jar包
定义一个方法,在方法上写注解:@Test
执行方法:
a点击该方法的左边的绿色按钮,点击执行run执行->单独执行一个指定的方法
b:如果想要执行所有带@Test的方法,点击类名左边的绿色按钮,点击run执行->执行当前类中所有带@Test的方法
Junit的注意事项
@Test不能修饰static方法
@Test不能修饰带参数的方法
@Test不能修饰带返回值的方法
import org.junit.Test;
public class Demo01Junit {
@Test
public void add(){
System.out.println("我是@Test的执行add方法");
}
@Test
public void delete(){
System.out.println("我是@Test的执行delete方法");
}
}
Junit相关注解
@Before:在@Test前执行,有多少@Test执行,@Before就执行多少次->都是用作初始化一些数据
@After:在@Test之后执行,有多少个@Test执行,@After就执行多少次->用作释放资源使用
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class Demo02Junit {
@Test
public void add(){
System.out.println("我是@Test的执行add方法");
}
@Test
public void delete(){
System.out.println("我是@Test的执行delete方法");
}
@Before
public void methodBefore(){
System.out.println("我是Before执行的方法");
}
@After
public void methodAfter(){
System.out.println("我是After执行的方法");
}
}
其他注解:(了解)
@Beforeclass:在@Test之前执行,只执行一次,可以修饰静态方法
@AfterClass:在@Test之后执行,只执行一次,可以修饰静态方法
二、反射
1.介绍
反射的概述:解剖class对象的一个技术
问题:能解剖class对象的啥呢?
a:解剖出成员变量:赋值
b:解剖出成员方法:调用
c:解剖出构造方法:new对象
用反射的好处:让代码变得更通用,更灵活
怎么学反射?
a:将反射看成是一套API来学
b:同伙案例,体会好处
问题:玩反射,最开始的一步是干啥?
获取class对象
class对象:是class文件对应的对象
Class类:描述class的对象的类叫做class类
2.反射之获取class对象
方式一:调用object中的getclass方法:
Class<?> getClass()
方式二:不管是基本类型还是引用类型,jvm都为其提供了一个静态成员:class
方式三:Class类中的静态方法:
Static Class<?> forName(String className)
ClassName:传递的是类的全限定名(包名,类名)
import org.junit.Test;
public class Demo01GetClass {
@Test
public void get1() throws Exception{
/* 1.调用object中的getclass方法:
Class<?> getClass()*/
Person person = new Person();
Class<? extends Person> aClass = person.getClass();
System.out.println(aClass);
System.out.println("=====================");
//2.不管是基本类型还是引用类型,jvm都为其提供了一个静态成员:class
Class<Person> aClass1 = Person.class;
System.out.println(aClass1);
System.out.println("===========");
/* 3.Class类中的静态方法:
Static Class<?> forName(String className)
ClassName:传递的是类的全限定名(包名,类名)*/
Class<?> aClass2 = Class.forName("com.ykm.b_reflect.Person");
System.out.println(aClass2);
System.out.println(aClass1==aClass2);
}
}
三种获取class对象的方式最通用的一种
方式三:Class类中的静态方法:
Static Class<?> forName(String className)
ClassName:传递的是类的全限定名(包名,类名)
原因:参数String形式可以和properties文件结合使用
开发中最常用的是哪一种
直接类名.class->最方便使用
3.获取Class对象中的构造方法
(API)找对象方法获取功能
获取所有public的构造方法
Class类中的方法:
Constructor<?>[] getConstructors() ->获取所有public的构造
import java.lang.reflect.Constructor;
public class Demo03GetConstructor {
public static void main(String[] args) {
//获取Class对象
Class<Person> aClass = Person.class;
//获取所有public的构造
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
}
}
4.获取空参构造_public
Constructor<T> getConstructor(Class<?>.....parameterTypes) ->获取指定的public的构造
parameterTypes:参数类型,可变参数,可以传0个或者多个参数
如果获取的是空参构造:参数不写
如果是获取的是有参构造:参数写参数类型的Class对象
Constructor类中的方法:
NewInstance(Object...intargs)->创建对象
.intargs:传递的是构造方法中的实参
如果根据无参构造new对象,initargs不写了
如果根据有参构造new对象,initargs传递实参
import java.lang.reflect.Constructor;
public class Demo04GetConstructor {
public static void main(String[] args) throws Exception{
//获取Class对象
Class<Person> aClass = Person.class;
Constructor<Person> constructor = aClass.getConstructor();
System.out.println(constructor);
/*
* 好比是person person=new person()
* */
Person person = constructor.newInstance();
System.out.println(person);
}
}
5.利用空参构造创建对象的快捷方式_public
Class类中的方法:
T newInstance()->.根据空参构造创建对象
前提:被反射的类中必须有public的空参构造
import java.lang.reflect.Constructor;
public class Demo05GetConstructor {
public static void main(String[] args) throws Exception{
//获取Class对象
Class<Person> aClass = Person.class;
Constructor<Person> constructor = aClass.getConstructor(String.class, Integer.class);
System.out.println(constructor);
//创建对象
Person person = constructor.newInstance("名", 18);
System.out.println(person);
}
}
6.利用反射获取有参构造并创建对象_public
Class类中的方法:
Constructor<T> getConstructor(class<?>.......parameterTypes)->获取指定的public的构造
parameterTypes:可变参数,可以传递0个或者多个参数
如果获取的是空参构造:参数不用写
如果获取的是有参构造:参数写参数类型的class对象
Constructor类中的方法:
T newInstance(Object.....initargs)->创建对象
initargs:传递的是构造方法的实参
如果根据无参构造new对象,initargs不写了
如果根据有参构造new对象,initargs传递实参
import java.lang.reflect.Constructor;
public class Demo06GetConstructor {
public static void main(String[] args) {
Class<Person> aClass = Person.class;
Constructor<?>[] dc = aClass.getDeclaredConstructors();
for (Constructor<?> constructor : dc) {
System.out.println(constructor);
}
}
}
7.利用反射获取私有构造(暴力反射)
Constructor<?>[] getDeclaredConstructors()获取所有的构造方法,包括private
Constructor<T> getDeclaredConstructor(类<?>......parameterTypes)->获取指定构造,包括private
parameterTypes:参数类型的class对象
Constructor有一个父类叫做AccessibleObject,里面有一个方法
void setAccessible(boolean flag)->.修改访问权限
flag为true:解除私有权限
import java.lang.reflect.Constructor;
public class Demo07GetConstructor {
public static void main(String[] args)throws Exception {
Class<Person> aClass = Person.class;
Constructor<Person> dc = aClass.getDeclaredConstructor(String.class);
dc.setAccessible(true);//接触私有权限->暴力反射
Person person = dc.newInstance("名");
System.out.println(person);
}
}
8.反射成员方法
(1)利用反射获取所有成员方法_public
Class类中方法:
Method[] getMethods()->获取所有public的方法,包括父类中的public方法
(2)反射之获取方法(有参,无参)_public
Class类中的方法:
Method getMethod(String name,Class<?>.....parameterTypes)获取指定的public的成员方法
Name:传递方法名
ParameterTypes:方法参数类型的class对象
调用方法:Method对象中的方法
Object invoke(Object obj,Object.....args)->执行方法
Obj:根据构造new出来的对象
Args:方法实参->如果有参数,直接传递实参;否则不用传
9.反射成员变量
Class类中的方法:
Filed[] getFields()->获取所有public的属性
Filed[] getDeclaredFields()->获取所有属性,包括private的
获取指定的属性
Class类中的方法:
Filed getField(String name)->获取指定public的属性
Filed getDeclaredField(String name)->获取指定属性,包括private的
Field类中的方法:
Void set(Object obj,Object value)->为属性赋值,相当一Javabean中的set方法
Obj:对象
Value:赋予的值
Object get(Object obj)->获取属性值
Obj:对象
import java.lang.reflect.Field;
public class Demo08GetFiled {
public static void main(String[] args)throws Exception {
// method01();
// method02();
method03();
}
/*
Filed getDeclaredField(String name)->获取指定属性,包括private的
* */
private static void method03() throws Exception{
Class<Student> studentClass = Student.class;
Student student = studentClass.newInstance();
Field name = studentClass.getDeclaredField("name");
//解除私有权限
name.setAccessible(true);
//调用set方法赋值
name.set(student,"名");
//调用get
Object o = name.get(student);
System.out.println(o);
}
/*
*Filed getField(String name)->获取指定public的属性
*
* */
private static void method02() throws Exception{
Class<Student> studentClass = Student.class;
Student student = studentClass.newInstance();
Field age = studentClass.getField("age");
//调用set方法赋值
age.set(student,10);
//调用get
Object o = age.get(student);
System.out.println(o);
}
private static void method01() {
Class<Student> studentClass = Student.class;
Field[] fields = studentClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("=============");
Field[] df = studentClass.getDeclaredFields();
for (Field field : df) {
System.out.println(field);
}
}
}
10.反射之操作私有方法
Method[] getDeclareMethods()
Method[] getDeclareMethod(String name,类<?>.....parameterTypes)->获取执行成员方法,包括private
name:传递方法名
parameterTypes:方法参数类型的class对象
解除私有权限:void setAccessible(boolean flag)
import java.lang.reflect.Method;
public class Demo09GetMethod {
public static void main(String[] args) throws Exception {
// method01();
// method02();
// method03();
method04();
}
/*
* 反射指定的方法包括private
* */
private static void method04()throws Exception {
Class<Person> aClass = Person.class;
Person person = aClass.newInstance();
Method eat = aClass.getDeclaredMethod("eat");
eat.setAccessible(true);
eat.invoke(person);
}
/*
*
* 获取所有成员方法包括private
* */
private static void method03() {
Class<Person> aClass = Person.class;
Method[] dm = aClass.getDeclaredMethods();
for (Method method : dm) {
System.out.println(method);
}
}
/*
* 获取指定的public的方法
* */
private static void method02() throws Exception{
Class<Person> aClass = Person.class;
//创建对象
Person person = aClass.newInstance();
Method setName = aClass.getMethod("setName", String.class);
setName.invoke(person,"名");
System.out.println(person);//好比调用tostring方法
System.out.println("=============");
Method getName = aClass.getMethod("getName");
Object invoke = getName.invoke(person);
System.out.println(invoke);
}
/*
* 获取所有public的方法
*
* */
private static void method01() {
Class<Person> aClass = Person.class;
Method[] method = aClass.getMethods();
for (Method method1 : method) {
System.out.println(method1);
}
}
}
三、注解
1.注解的介绍
引用数据类型:类 数组 接口 枚举 注解
jdk1.5版本的新特性->一个引用数据类型和类,接口,枚举是同一个层次的
作用:
说明:对代码进行说明,生成doc文档(API文档)
检查:检查文档是否符合条件 @Override(会用) @FunctionalInterface
分析:对代码进行分析,起到了代替配置文件的作用(会用)
JDK中的注解:
@Override->检测此方法是否为重写方法
jdk1.5版本,支持父类的方法重写
jdk1.6版本,支持接口的方法重写
2.注解的定义以及属性的定义格式
大家需要知道的是,咱们这里说的注解属性,其实本质上是抽象方法,但是我们按照属性来理解,好理解,因为到时候使用注解的时候,需要=为其赋值
定义:
public @interface 注解名{
}
定义属性:增强注解的作用
数据类型 属性名()->此属性没有默认值,需要在使用注解的时候为其赋值
数据类型 属性名() default 值->此属性有默认值,如果有需要,还可以二次赋值
注解中能定义什么类型的属性呢?
8种基本类型
String类型,Class类型,枚举类型,注解类型
以及以上类型的一维数组
public @interface Book {
//书名
String bookName();
//作者
String[] author();
//价格
int price();
//数量
int count() default 10;
}
注解的使用
就是为注解中的属性赋值
使用位置:类,方法,成员变量,局部变量,参数位置等
使用格式
@注解名(属性名=值,属性名=值.....)
如果属性中有数组:@注解名(属性名={元素一,元素二.......})
@Book(bookName = "水浒传",author = "施耐庵",price = 50,count = 20)
public class BookShelf {
}
注解注意事项:
空注解可以直接使用->空注解就是注解中没有任何的属性
不同位置的可以使用一样的注解,但是同样的位置不能使用一样的注解
使用注解时,如果此注解中有属性,注解中的属性一定要赋值,如果有多个属性用,隔开
如果注解中的属性有数组,使用{}
如果注解中的属性值有默认值,那么我们不必要写,也不用重新赋值,反之必须协商
如果注解种只有一个属性,并且属性名叫value,那么使用注解的时候,属性名不用写,直接写值(包括单个类型,还包括数组)
注解解析的方法->AnnotatedElement接口
注解的解析:说白了就是将注解中的属性值获取出来
注解的解析涉及到的接口:AnnotatedElement接口
3.元注解
概述:元注解就是管理注解的注解
从那些方面管理呢?
a:控制注解的使用位置
控制注解是否能在类(方法、构造)上使用
b:控制注解的生命周期(如加载位置)
控制注解是否能在源码(class、内存)中出现
怎么使用
a:@Target:控制注解的使用位置
属性:ElementType[] value();
ElementType是一个枚举,里面的成员可以类名直接调用
ElementType中的成员:
TYPE:控制注解能使用在类上
FIELD:控制注解能使用在属性上
METHOD:控制注解能使用在方法上
PARAMETER:控制注解能使用在参数上
CONSTRUCTOR:控制注解能使用在构造上
LOCAL_VARIABLE:控制注解能使用在局部变量上
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface Book {
//书名
String bookName();
//作者
String[] author();
//价格
int price();
//数量
int count() default 10;
}
四、枚举
1.介绍
概述:五大引用数据类型之一(类 数组 接口 注解 枚举)
定义:
Public enum 枚举类名{ }
所有的枚举为父类都是Enum
定义枚举值
a:枚举值特点:都是static final,但是定义的时候不要写出来,写出来报错
写完所有的枚举值之后,最后加个;枚举值名字要大写->开发习惯
b:类名直接调用
c:注意:每一个枚举值都是当前枚举类的对象
问题:枚举类中的枚举值都是什么类型的呢? 本类类型
枚举类中其他成员:构造
在枚举类中定义的构造,默认的都是private的
枚举的使用场景:表示对象的状态
public enum State {
//State WEIFUKUAN=new State()
//State WEIFUKUAN=new State("未付款")
WEIFUKUAN("未付款"),
YIFUKUAN("已付款"),
WEIFAHUO("未发货"),
YIFAHUO("已发货");
private String name;
State() {
}
State(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.枚举的方法
方法名 | 说明 |
---|---|
String toString() | 返回枚举值的名字 |
values() | 返回所有与的枚举值 |
valueOf(String str) | 将一个字符串转成枚举类型 |
public class Test01 {
public static void main(String[] args) {
State weifahuo = State.WEIFAHUO;
System.out.println(weifahuo.getName());
System.out.println("================");
String s = State.WEIFUKUAN.toString();
System.out.println(s);
System.out.println("=========");
State[] values = State.values();
for (State value : values) {
System.out.println(value);
}
}
}