- Junit介绍 (***** 了解 *****)
Java Unit Java单元测试框架
Junit是Java语言编写单元测试框架,最直观的理解,就是取代java类中的main方法。Junit属于第三方工具,一般情况下需要导入jar包,而多数Java开发环境都集成了Junit。
Junit的使用
创建“MyJunit”java项目,并创建“cn.itcast.junit”包
- 编写测试类,简单理解Junit可以用于取代java的main方法
- 在测试类方法上添加注解 @Test
- @Test修饰的方法要求:public void 方法名() {…} ,方法名自定义建议test开头,没有参数。
- 添加Eclipse中集成的Junit库,鼠标点击“@Test”,使用快捷键“ctrl + 1”,点击“Add Junit …”
结果
- 使用:选中方法右键,执行当前方法;选中类名右键,执行类中所有方法(方法必须标记@Test)
- 常用注解
@Test,用于修饰需要执行的方法
@Before,测试方法前执行的方法
@After,测试方法后执行的方法
- import org.junit.After;
- import org.junit.Before;
- import org.junit.Test;
- public class JunitDemo {
- @Before
- public void test_Before() {
- System.out.println("Before 注解的方法 ...");
- }
- @After
- public void test_After() {
- System.out.println("After 注解的方法 ...");
- }
- @Test
- public void test_01() {
- System.out.println("测试 test01 方法 ...");
- }
- @Test
- public void test_02() {
- System.out.println("测试 test02 方法 ...");
- }
- @Test
- public void test_03() {
- System.out.println("测试 test03 方法 ...");
- }
- }
- 常见使用错误,如果没有添加“@Test”,使用“Junit Test”进行运行,将抛异常
- 类加载器 (***** 了解 *****)
类加载器:类加载器是负责加载类的对象。将class文件(硬盘)加载到内存生成Class对象。
所有的类加载器 都是 java.lang.ClassLoader 的子类
类的加载说明 :
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构.
注意 : 只有Java虚拟机才能创建class类的对象.
重点 : 类加载的最终产品是位于堆区中的 Class对象.
Class对象封装了类在方法区内的数据结构 ,并且向Java程序员提供了访问方法区内的数据结构的接口,这些接口都定义在了 `反射` 包中.
- 引导类加载器
- package cn.itcast.classloader;
- import java.util.Properties;
- import org.junit.Test;
- public class ClassLoaderDemo01 {
- @Test
- public void demo01() {
- // 确定引导类加载器类型: null
- ClassLoader cl = String.class.getClassLoader();
- System.out.println(cl);
- }
- }
2. 扩展类加载器
- package cn.itcast.classloader;
- import org.junit.Test;
- import sun.net.spi.nameservice.dns.DNSNameService;
- public class ClassLoaderDemo02 {
- @Test
- public void demo01() {
- // 添加项目访问规则 -> Properties -> BuildPath -> Library
- // -> JRE System -> Access rules -> Edit -> add -> sun/**
- // 确定扩展类加载器类型: Launcher$ExtClassLoader
- ClassLoader cl = DNSNameService.class.getClassLoader();
- System.out.println(cl);
- }
- }
3. 应用类加载器
- package cn.itcast.classloader;
- import org.junit.Test;
- import sun.net.spi.nameservice.dns.DNSNameService;
- public class ClassLoaderDemo03 {
- @Test
- public void demo03() {
- // 确定应用类加载器类型: Launcher$AppClassLoader
- ClassLoader cl = ClassLoaderDemo03.class.getClassLoader();
- System.out.println(cl);
- }
- }
4. 类加载器之间的关系
- package cn.itcast.classloader;
- import org.junit.Test;
- public class ClassLoaderDemo04 {
- @Test
- public void demo01() {
- // 验证三个类加载器之间的关系:
- ClassLoader cl1 = ClassLoaderDemo04.class.getClassLoader();
- System.out.println(cl1); // AppClassLoader
- ClassLoader cl2 = cl1.getParent();
- System.out.println(cl2); // ExtClassLoader
- ClassLoader cl3 = cl2.getParent();
- System.out.println(cl3); // null
- }
- }
- 反射详解 (***** 了解 *****)
反射概述 :
Java反射机制是在运行状态中,对指定的类,任意的方法或任意的字段进行操作,这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制。
简而言之,反射就是:在运行时通过代码操作类。
想要操作类,就必须先获得该类的字节码对象Class 对象。通过Class提供的方法对类进行进一步的解剖,从而实现各种操作。
在进行具体操作之前,大家需要先掌握类各个组成的专业描述
Class类
Constructor 构造方法
Method 方法
Field 字段 / 属性
instance 实例 / 实例对象
invoke 调用, 执行
- 三种获取Class对象的方式
- /*
- * 不同的应用场景, 需要使用不同的方式获取 Class 对象.
- *
- * 1. 通过字符串 (全限定名) 获得. `包名 + 类名`
- * 格式 : Class cls = Class.forName("字符串");
- * 场景 : 开发中, 从配置文件中获取 `全限定类名`, 并通过反射进行所有操作.
- *
- * 2. 通过 Java 类型获取.
- * 格式 : Class cls = 类名.class;
- * 场景 : 确定方法形参列表时, 需要通过类型获得.
- * 例如 : public void init(String s, int i) {}
- * 类型对应的Class参数列表为: init(String.class, int.class);
- *
- * 3. 通过实例对象获得.
- * 格式 : Class cls = obj.getClass();
- * 场景 : 方法内部通过变量名(实例对象名)获得.
- * 例如 : public void init(Object obj) {
- * obj.getClass();
- * }
- */
- public class ClassDemo {
- @Test
- public void demo01() throws ClassNotFoundException {
- Class<?> cls = Class.forName("cn.itcast.practice.ClassDemo");
- System.out.println(cls);
- }
- @Test
- public void demo02() {
- Class<?> cls = String.class;
- System.out.println(cls);
- }
- @Test
- public void demo03() {
- Object obj = new String();
- Class<?> cls = obj.getClass();
- System.out.println(cls);
- }
- }
- 供一个 Student类, 用于之后的反射操作
- package cn.itcast.reflect;
- // 提供 Student 类, 用于之后的反射操作.
- public class Student {
- public static void main(String[] args) {
- System.out.println("Student 类的 main 方法被调用... ");
- System.out.println("args[0]=" + args[0] + ", args[1]=" + args[1]);
- }
- // 属性
- private String name;
- private int age;
- public String description;
- // 无参构造方法
- public Student() {
- System.out.println("无参构造方法被调用...");
- }
- public Student(String name, int age) {
- System.out.println("带 String name, int age 参数的构造方法被调用...");
- this.name = name;
- this.age = age;
- }
- // 私有构造方法
- private Student(String name, int age, String description) {
- System.out.println("私有构造方法被调用...");
- this.name = name;
- this.age = age;
- this.description = description;
- }
- // 私有方法
- private void show(int num) {
- System.out.println("私有方法: " + num);
- }
- public String getDescription() {
- return description;
- }
- public void setDescription(String description) {
- this.description = description;
- }
- 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;
- }
- @Override
- public String toString() {
- return "Student [name=" + name + ", age=" + age + ", description=" + description + "]";
- }
- }
- 使用反射调用构造方法创建对象
- package cn.itcast.reflect;
- import java.lang.reflect.Constructor;
- import org.junit.Test;
- public class ConstructorDemo {
- // 普通方式 : 直接 new 对象.
- @Test
- public void demo01() {
- // 触发 `无参构造方法`
- // Student stu = new Student();
- // 触发 `有参构造方法`
- // Student stu = new Student("Jack", 30);
- // 触发 `私有构造方法` 错误!
- // Student stu = new Student("Jack", 30, "学霸");
- // System.out.println(stu);
- }
- // 通过反射调用无参构造方法获得实例对象
- @Test
- public void demo02() throws Exception {
- // 1. 获取Class对象
- Class<?> cls = Class.forName("cn.itcast.reflect.Student");
- // 2. 通过cls直接创建对象, 相当于: new Student();
- Object obj = cls.newInstance();
- }
- // 通过反射调用有参构造方法, 获得实例对象
- @Test
- public void demo03() throws Exception {
- // 1. 获取Class对象
- Class<?> cls = Class.forName("cn.itcast.reflect.Student");
- // 2. 获得构造方法, 相当于: Student(String name, int age);
- // getConstructor(Class<?>... parameterTypes)
- Constructor<?> cons = cls.getConstructor(new Class[]{String.class, int.class});
- // 3. 调用构造方法, 获得实例对象, 相当于: new Student();
- // newInstance(Object ... initargs)
- Object obj = cons.newInstance(new Object[]{"Jack", 30});
- System.out.println(obj);
- }
- // 通过私有构造方法获得实例对象
- @Test
- public void demo04() throws Exception {
- // 1. 获取 Class 对象
- Class<?> cls = Class.forName("cn.itcast.reflect.Student");
- // 2. 获取构造方法
- Constructor<?> cons = cls.getDeclaredConstructor(new Class[]{String.class, int.class, String.class});
- // 暴力访问 (默认不允许)
- cons.setAccessible(true);
- // 3. 调用构造方法, 获得实例对象
- Object obj = cons.newInstance(new Object[]{"Jack", 30, "学霸"});
- System.out.println(obj);
- }
- }
- 使用反射执行方法
- package cn.itcast.reflect;
- import java.lang.reflect.Method;
- import org.junit.Test;
- public class MethodDemo {
- @Test
- public void demo01() {
- Student stu = new Student();
- stu.setName("Jack");
- stu.setAge(30);
- System.out.println(stu);
- String name = stu.getName();
- int age = stu.getAge();
- System.out.println("name: " + name + ", age: " + age);
- // stu.show(); 错误! 无法调用私有方法.
- }
- @Test
- public void demo02() throws Exception {
- // 1. 获得实例
- Class<?> cls = Class.forName("cn.itcast.reflect.Student");
- Object obj = cls.newInstance();
- // 2.1 获取 setName(String name) 方法
- Method setNameMethod = cls.getMethod("setName", String.class);
- // 2.2 调用方法, 传递实际参数
- setNameMethod.invoke(obj, "Jack");
- // 2.3 获取 setAge(int age) 方法
- Method setAgeMethod = cls.getMethod("setAge", int.class);
- // 2.4 调用
- setAgeMethod.invoke(obj, 30);
- System.out.println(obj);
- // Method getNameMethod = cls.getMethod("getName", null);
- // Object name = getNameMethod.invoke(obj, null);
- // Method getAgeMethod = cls.getMethod("getAge", null);
- // Object age = getAgeMethod.invoke(obj, null);
- Method getNameMethod = cls.getMethod("getName");
- Object name = getNameMethod.invoke(obj);
- Method getAgeMethod = cls.getMethod("getAge");
- Object age = getAgeMethod.invoke(obj);
- System.out.println("name: " + name + ", age: " + age);
- }
- @Test
- public void demo03() throws Exception {
- // 1. 获得实例
- Class<?> cls = Class.forName("cn.itcast.reflect.Student");
- Object obj = cls.newInstance();
- // 2. 获取方法并调用执行
- Method showMethod = cls.getDeclaredMethod("show", int.class);
- showMethod.setAccessible(true); // 暴力访问
- Object result = showMethod.invoke(obj, 100);
- // 如果方法没有返回结果, 那么结果为 null
- System.out.println(result);
- }
- // 执行静态方法 main, 无需获得实例, 但是必须要获得 Class 对象
- @Test
- public void demo04() throws Exception {
- // 1. 获得 Class 对象
- Class<?> cls = Class.forName("cn.itcast.reflect.Student");
- // 2. 获得 main 方法
- Method mainMethod = cls.getMethod("main", new Class[]{String[].class});
- // 特点注意 : 数组类型的参数书写格式
- mainMethod.invoke(null, new Object[]{new String[]{"Hello", "World"}});
- }
- }
可变参数的方法调用方式 :
- 使用反射获取属性
- package cn.itcast.reflect;
- import java.lang.reflect.Field;
- import org.junit.Test;
- public class FieldDemo {
- @Test
- public void demo01() {
- Student stu = new Student();
- stu.description = "描述信息";
- System.out.println(stu);
- }
- @Test
- public void demo02() throws Exception {
- // 1. 获得实例
- Class<?> cls = Class.forName("cn.itcast.reflect.Student");
- Object obj = cls.newInstance();
- // 2. 获得属性
- Field descField = cls.getField("description");
- descField.set(obj, "描述信息: 学霸");
- System.out.println(obj);
- }
- @Test
- public void demo03() throws Exception {
- // 1. 获得实例
- Class<?> cls = Class.forName("cn.itcast.reflect.Student");
- Object obj = cls.newInstance();
- // 2. 获得属性并设置数值
- Field nameField = cls.getDeclaredField("name");
- nameField.setAccessible(true);
- nameField.set(obj, "Jack");
- Field ageField = cls.getDeclaredField("age");
- ageField.setAccessible(true);
- ageField.set(obj, 30);
- System.out.println(obj);
- // 查看属性
- Object name = nameField.get(obj);
- Object age = ageField.get(obj);
- System.out.println("name: " + name + ", age: " + age);
- }
- }
- 反射综合案例 – 举办晚会 (***** 练习 *****)
party.properties
- #singable=cn.itcast.classloader.LiuDeHua
- #dancable=cn.itcast.classloader.GirlsTeam
- #performable=cn.itcast.classloader.LiuQian
- singable=cn.itcast.classloader.ZhangXueYou
- dancable=cn.itcast.classloader.GirlsGeneration
- performable=cn.itcast.classloader.ZhaoBenShan
Dancable
- package cn.itcast.classloader;
- public interface Dancable {
- void dance();
- }
Singable
- package cn.itcast.classloader;
- public interface Singable {
- void sing();
- }
Performable
- package cn.itcast.classloader;
- public interface Performable {
- void perform();
- }
PartyFactory
- package cn.itcast.classloader;
- import java.io.FileReader;
- import java.io.IOException;
- import java.util.Properties;
- public class PartyFactory {
- private static Properties prop = new Properties();
- static {
- try {
- prop.load(new FileReader("party.properties"));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- public static Singable getSingable() throws Exception {
- String className = prop.getProperty("singable");
- Class<?> cls = Class.forName(className);
- return (Singable) cls.newInstance();
- }
- public static Dancable getDanceble() throws Exception {
- String className = prop.getProperty("dancable");
- Class<?> cls = Class.forName(className);
- return (Dancable) cls.newInstance();
- }
- public static Performable getPerformable() throws Exception {
- String className = prop.getProperty("performable");
- Class<?> cls = Class.forName(className);
- return (Performable) cls.newInstance();
- }
- }
EveningParty
- package cn.itcast.classloader;
- public class EveningPartyDemo {
- public static void main(String[] args) throws Exception {
- System.out.println("晚会开始了...");
- // 歌曲
- Singable singable = PartyFactory.getSingable();
- singable.sing();
- // 舞蹈
- Dancable danceble = PartyFactory.getDanceble();
- danceble.dance();
- // 表演
- Performable performable = PartyFactory.getPerformable();
- performable.perform();
- System.out.println("难忘今宵!");
- }
- }
ZhangXueYou
- package cn.itcast.classloader;
- public class ZhangXueYou implements Singable {
- @Override
- public void sing() {
- System.out.println("张学友 演唱 `一路上有你`!");
- }
- }
GirlsGeneration
- package cn.itcast.classloader;
- public class GirlsGeneration implements Dancable {
- @Override
- public void dance() {
- System.out.println("少女时代 跳 Gee Gee Gee!");
- }
- }
ZhaoBenShan
- package cn.itcast.classloader;
- public class ZhaoBenShan implements Performable {
- @Override
- public void perform() {
- System.out.println("赵本山 表演 `卖拐`!");
- }
- }
LiuDeHua
- package cn.itcast.classloader;
- public class LiuDeHua implements Singable {
- @Override
- public void sing() {
- System.out.println("刘德华 演唱 `爱你一万年`!");
- }
- }
GirlsTeam
- package cn.itcast.classloader;
- public class GirlsTeam implements Dancable {
- @Override
- public void dance() {
- System.out.println("女子团队 跳 `性感广场舞`!");
- }
- }
LiuQian
- package cn.itcast.classloader;
- public class LiuQian implements Performable {
- @Override
- public void perform() {
- System.out.println("刘谦 表演 `大变活人`!");
- }
- }