Junit & 反射

 Junit介绍

            Junit是Java语言编写单元测试框架,最直观的理解,就是取代java类中的main方法。Junit属于第三方工具,一般情况下需要导入jar包,而多数Java开发环境都集成了Junit。

    使用方式

  1. 编写测试类,简单理解Junit可以用于取代java的main方法
  2. 在测试类方法上添加注解 @Test
  3. @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()方法创建对象

            步骤:

  1. 获得Class对象
  2. 通过Class类中的newInstance()方法创建对象

    通过获取public的构造创建对象

        步骤:

  1. 获得Class对象

        2获得构造

  1. 通过构造对象获得实例化对象
    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);
    	}
    }
    

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值