Junit介绍
Junit是Java语言编写单元测试框架,最直观的理解,就是取代java类中的main方法。Junit属于第三方工具,一般情况下需要导入jar包,而多数Java开发环境都集成了Junit。
使用方式
- 编写测试类,简单理解Junit可以用于取代java的main方法
- 在测试类方法上添加注解 @Test
- @Test修饰的方法要求:public void 方法名() {…} ,方法名自定义建议test开头,没有参数。
package com.junitTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* @author :Andy
* @date :Created in 2019/6/17 20:25
* @description:编写测试类
*/
public class JunitTest1 {
@Test
public void test01(){
System.out.println("运行test01");
}
@After
public void test02(){
System.out.println("运行test02");
}
@Before
public void test03(){
System.out.println("运行test03");
}
}
类的加载
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
加载
就是指将class文件读入内存,并为之创建一个Class对象。
任何类被使用时系统都会建立一个Class对象
连接
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用
初始化
就是我们以前讲过的初始化步骤
类的初始化
1. 创建类的实例
2. 类的静态变量,或者为静态变量赋值
3. 类的静态方法
4. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
5. 初始化某个类的子类
6. 直接使用java.exe命令来运行某个主类
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖这个类,使用的就是Class类中的方法,所以先要获取到每一个字节码文件所对应的Class类型对象。
反射需要用到的成员及方法:
n Class类
n Constructor 构造
n Method 方法
n Field 字段
n instance 实例
n invoke 执行
反射数据准备
提供JavaBean,用于之后反射操作 JavaBean规范
1.提供私有字段,例如:private String id;
2.必须提供getter或setter方法 (可以使用快捷键生产,alt+shift+s)
3.提供无参构造方法
package com.Reflect;
/**
* @author :Andy
* @date :Created in 2019/6/17 20:49
* @description:学生类
*/
public class Student {
private String name;
private int age;
private String sex;
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Student() {
}
public Student(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
}
三种获取方式及应用场景
1 通过类型获得
语法:类名.class
应用场景:确定类型 等
Class clazz1 = Bean.class;
2 通过实例对象获得
语法:对象.getClass()
应用场景:在方法内部通过参数获得类型 等
Bean bean = new Bean();
Class clazz2 = bean.getClass();
3 通过字符串获得
语法:Class.forName("全限定类名")
应用场景:通过配置获得字符串 等
Class clazz3 = Class.forName("com.igeek_00_Bean.Bean");
package com.reflectDemo;
import org.junit.Test;
/**
* @author :Andy
* @date :Created in 2019/6/17 20:53
* @description:三种获得方式
*/
public class ReflectTest01 {
@Test
public void test1(){
//一直明确的类名,获取Class 对象
Class clazz = Student.class;
System.out.println(clazz);
}
@Test
public void test2(){
//已知对象获取class对象
Student s1 = new Student();
Class clazz = s1.getClass();
System.out.println(clazz);
}
@Test
public void test3() throws ClassNotFoundException {
//3、全限定类名(包名.类名),获取Class对象 *****常用
Class<?> clazz = Class.forName("com.igeek.javaadvancedday8.javaadvance2day01.Student");
System.out.println(clazz);
}
@Test
public static void main(String[] args) throws ClassNotFoundException {
Class clazz1 = Student.class;
Student s1 = new Student();
Class clazz2 = s1.getClass();
String className = "com.igeek.javaadvancedday8.javaadvance2day01.Student";
Class clazz3 = Class.forName(className);
System.out.println(clazz1==clazz2);
System.out.println(clazz2==clazz3);
}
}
通过newInstance()方法创建对象
如果类中有public的无参构造器,可以使用Class类中的newInstance()方法创建对象
步骤:
- 获得Class对象
- 通过Class类中的newInstance()方法创建对象
通过获取public的构造创建对象
步骤:
- 获得Class对象
2获得构造
- 通过构造对象获得实例化对象
public class ReflectTest01 { @Test public void test01() { // 1、创建实例 Student s1 = new Student(); System.out.println(s1); // 2、利用实例去调用成员方法 s1.setId(20); System.out.println(s1); } @Test public void test02() throws Exception { // 1、创建该类的Class对象 String className = "com.igeek_02.Student"; Class clazz = Class.forName(className); // 2、获取构造器,利用构造器的newInstance方法创建实例 Object s1 = clazz.newInstance(); System.out.println(s1); // 3、获取成员方法 Method m_setId = clazz.getMethod("setId", int.class); // 4、使用成员方法中的invoke方法去调用该方法 m_setId.invoke(s1, 20); System.out.println(s1); } // 获取方法的返回值问题 @Test public void test03() throws Exception { // 1、创建该类的Class对象 String className = "com.igeek_02.Student"; Class clazz = Class.forName(className); // 2、获取构造器,利用构造器的newInstance方法创建实例 Object s1 = clazz.newInstance(); System.out.println(s1); // 3、获取成员方法 Method m_getId = clazz.getMethod("getId"); // 4、使用成员方法中的invoke方法去调用该方法 Object returnValue = m_getId.invoke(s1); System.out.println("returnValue:" + returnValue); } // 如何调用私有成员方法 @Test public void test04() throws Exception { // 1、创建该类的Class对象 String className = "com.igeek_02.Student"; Class clazz = Class.forName(className); // 2、获取构造器,利用构造器的newInstance方法创建实例 Object s1 = clazz.newInstance(); System.out.println(s1); //3、获取私有成员方法setName //利用getDeclaredMethod(String name, Class<?>... parameterTypes) Method m_setName = clazz.getDeclaredMethod("setName",String.class); System.out.println("m_setName:"+m_setName); //4、打破私有的访问界限 m_setName.setAccessible(true); m_setName.invoke(s1, "tom"); System.out.println(s1); } }
反射public字段
反射public字段执行流程
1 获得实例对象
2 给字段赋值
3 获得字段值
public class FieldTest01 { @Test public void test01(){ //给类中的public的字段赋值 Student s1=new Student(); s1.id=20; System.out.println(s1); } //类中公共字段 @Test public void test02() throws Exception{ //1、获取该类的Clazz类型对象 String className = "com.igeek_02.Student"; Class clazz = Class.forName(className); //2、创建该类的实例 Object s1=clazz.newInstance(); System.out.println(s1); //3、获取该类的字段 Field f_id=clazz.getField("id"); System.out.println("f_id:"+f_id); //4、给这个字段赋值 //void set(Object obj, Object value) f_id.set(s1, 20); System.out.println(s1); //5、获取字段的值 Object id_value=f_id.get(s1); System.out.println("id_value:"+id_value); } }
反射private字段
反射private字段流程
1 获得实例
2 获得声明的字段(私有)
3 设置运行访问私有(暴力)
4 设置数据
5 获得数据
public class FieldTest02 { //如何获取类中私有的字段 @Test public void test01() throws Exception{ //1、获取该类的Clazz类型对象 String className = "com.igeek_02.Student"; Class clazz = Class.forName(className); //2、创建该类的实例 Object s1=clazz.newInstance(); System.out.println(s1); //3、获取该类的私有字段 Field f_name=clazz.getDeclaredField("name"); System.out.println("f_name:"+f_name); //4、打破私有的访问限定 f_name.setAccessible(true); //5、赋值 f_name.set(s1, "tom"); System.out.println(s1); //6、拿值 Object s1_name=f_name.get(s1); System.out.println("s1_name:"+s1_name); } }