day17 反射常用API测试

一、先创建需要测试的Studnet类

package cn.sk.reflection;
/**本类用于测试反射,先准备物料类*/
public class Student {
    //1.定义成员变量
    public String name;
    public int age;

    //2.生成构造方法
    //右键空白处->Gennerate->Constryctor->Select None--无参构造/全选属性可以生成全参构造
    /**默认存在无参构造,创建对象时触发,若提供了含参构造
     * 默认的无参构造会被覆盖,注意手动添加无参构造*/
    public Student() {
        System.out.println("我是Student类无参构造");
    }

    public Student(String name, int age) {
        System.out.println("我是Student类的全参构造");
        this.name = name;
        this.age = age;
    }

    //3.创建普通成员方法
    public void study(){
        System.out.println("第一阶段马上要结束了,皮皮霞会更美");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

二、反射测试类

 

package cn.sk.reflection;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 本类用于测试反射
 */
public class Test1Reflect {
    //1.创建程序的入口函数main()--不用
    /**单元测试方法:是Java测试的最小范围,使用灵活,推荐程度:5颗星
     * 语法要求:@Test + void + 没有参数 + public
     * 注意:使用时需要导包:Add JUnit4 to ClassPath
     * */
    /**
     * 单元测试一:用来测试获取指定类的字节码对象
     */
    /*@Test*/
    public void getClazz() throws ClassNotFoundException {
        //1.方式1:通过类的全路径名[包名+类名]获取对应的字节码对象
        Class<?> student1 = Class.forName("cn.tedu.reflection.Student");
        //2.方式2:直接类名.Class获取对应的字节码对象
        Class<?> student2 = Student.class;
        //3.方式3:通过类的对象来获取,注意,此处创建的是匿名对象,匿名对象没有名字
        Class<?> student3 = new Student().getClass();

        System.out.println(student1);
        System.out.println(student2.getName());//cn.tedu.reflection.Student全路径
        System.out.println(student3.getSimpleName());//Student,获取类名
        System.out.println(student3.getPackage().getName());//cn.tedu.reflection获取包名

    }

    /**
     * 单元测试2:获取构造方法
     */
//    @Test
    public void getConstruct() {
        //1.get Class Object获取Student类的字节码对象
        Class<?> clazz = Student.class;
        //2.get Constructors and put it in array 通过字节码对象获取所有公开的构造方法
        Constructor<?>[] cs = clazz.getConstructors();
        //3.get Constructor by powerUp-for 通过增强for循环遍历存放所有构造函数的数组
        //for(1 2 :3){}3 表示的是要遍历的构造函数数组 1 表示当前遍历到的类型 2参数名
        for (Constructor<?> c : cs) {
            //通过本轮循环遍历到的构造函数对象,获取构造函数名
            System.out.println(c.getName());//get Constructor's name
            //通过本轮循环遍历到的构造函数对象,获取这个构造函数的参数类型
            Class<?>[] cp = c.getParameterTypes();//get Constructor's parameter type
            System.out.println(Arrays.toString(cp));
        }
    }

    /**
     * 单元测试3:获取普通方法
     */
    //@Test
    public void getFunction() throws ClassNotFoundException {
        //获取字节码对象
        Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
        //获取指定类中的所有普通方法
        Method[] ms = clazz.getMethods();
        //遍历存放所有方法的数组
        for (Method m : ms) {
            //通过当前遍历到的方法对象获取当前方法的名字
            System.out.println(m.getName());
            //通过当前遍历到的方法对象获取当前方法的参数类型
            Class<?>[] pt = m.getParameterTypes();
            System.out.println(Arrays.toString(pt));
        }
    }

    /**
     * 单元测试方法4:获取成员变量
     */
    //@Test
    public void getFields() throws ClassNotFoundException {
        /**注意!!!目前所有成员变量的修饰符必须是public才能获取到
         * 如果属性采用的是默认的修饰符,是反射不到的*/
        //1.获取字节码对象
        /**Class<?>中的"?"是泛型的约束通配符,类似"*"*/
        Class<?> clazz = Class.forName("cn.tedu.reflection.Student");

        //2.通过字节码队形获取所有的成员变量
        Field[] fields = clazz.getFields();

        //3.遍历
        for (Field field : fields) {
            System.out.println(field.getName());
            System.out.println(field.getType().getName());

        }
    }

    /**
     * 单元测试5:通过单元测试来反射创建对象
     * 方式一:通过字节码对象直接调用newInstance(),触发无参构造来创建对象
     * 方式二:先获取指定的构造函数,再通过构造函数对象调用newInstance,触发对应类型的构造函数来创建对象
     */
    @Test
    public void makeObject() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //1.获取class字节码对象
        Class<?> clazz = Class.forName("cn.tedu.reflection.Student");

        //2.创建对象
        Object o = clazz.newInstance();
        System.out.println(o);
        //3通过全参构造创建对象
        //3.1通过指定的构造函数创建对象
        /**注意参数类型的指定,是对应类型的字节码对象,不能直接光写类型*/
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        //3.2触发刚刚获取到的全参构造
        Object z = constructor.newInstance("张三", 18);/**此处是多态的向上造型*/
        System.out.println(z);
        /**查看对象具体的属性值,或者调用方法,需要把Object强转成指定的子类对象
         * 为什么要把Object转成子类类型呢?因为想要使用子类的属性或者是特有功能
         * 父类是无法使用子类的特有属性和功能,上面的obj2就是Object类型
         * Object类中没有Student中的属性和特有功能
         * 这种把之前看着是父类类型的子对象,重新转回成子类对象的现象,叫做向下造型
         * */
        Student s = (Student) z;
        System.out.println(s.name);
        System.out.println(s.age);
        s.study();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值