Java高级技术

Java高级技术


单元测试:Junit单元测试框架

针对于最小的功能单元方法,编写测试代码对于其进行正确性测试

自动测试全部方法

样例:

package junittest;

public class StringUtil {
    public static int getLength(String str) {
        if (str == null||"".equals(str)){
            return -1;
        }
        return str.length();
    }
    public static int getMaxIndex(String str){
        if (str == null||"".equals(str)){
            return -1;
        }
        return str.length();
    }
}

public class StringUtilTest {
    @Test
    public void testGetLength(){
        StringUtil.getLength("abc");
        StringUtil.getLength("");
        // StringUtil.getLength(null);
    }
    @Test
    public void testGetMaxIndex(){
        System.out.println(StringUtil.getMaxIndex("abc"));//实际上应该为2
        System.out.println(StringUtil.getMaxIndex(""));
        System.out.println(StringUtil.getMaxIndex(null));

    //     TODO:进行断言测试
        Assert.assertEquals("测试结果与预期目标不一致",2,StringUtil.getMaxIndex("abc"));
    }
}


反射(reflection)

用于加载类,并且允许已变成的方式 解剖类中的各种成分(成员变量,方法,构造器)

第一步:获取Class类对象

//     TODO:掌握反射:获取类的Class对象(获取类本身)
    // 通过类名获取Class
    Class c1 = Student.class;
    // 通过对象获取Class
    Class c2 = new Student().getClass();

第二步:获取类中的成分并进行操作

类中的成分:(Constructor构造器,Field成员变量,Method成员方法)

反射中建议调用getDeclaredXxx方法,获取的都是声明的成员变量和方法,包括私有的,不包括继承的

@Test
public void testGetClassInfo(){
    //     TODO:获取类的信息
    Student s = new Student("张三", 20, "清华大学");
    Class c = s.getClass();
    System.out.println(c.getName());
    System.out.println(c.getSimpleName());//获取类名
    //获取对应的构造器(getConstructors()获取所有构造器,其中返回的是该对象的公开的构造器的数组)
    System.out.println(Arrays.toString(c.getConstructors()));
    System.out.println(Arrays.toString(c.getMethods()));
}
@Test
public void testGetConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//     获取类的构造器
    Class c = Student.class;
    //获取所有的公开的构造器,并返回为一个数组 (getConstructors()获取所有构造器,其中返回的是该对象的公开的构造器的数组)
    System.out.println(Arrays.toString(c.getConstructors()));
    //获取所有的构造器,包括私有的,并返回为一个数组 (getDeclaredConstructors()获取所有构造器,其中返回的是该对象的所有构造器的数组)
    System.out.println(Arrays.toString(c.getDeclaredConstructors()));
// TODO:获取对应的无参构造器
    Constructor dc1 = c.getDeclaredConstructor();
    // TODO:获取对应的有参构造器
//     c.getConstructor(String.class,int.class,String.class);

//     TODO:获取构造器的作用是创建对象
//  如果构造器是私有的,那么我们就需要通过反射机制来创建对象
    dc1.setAccessible(true);//临时将构造器的权限设置为公开的
    Student s = (Student) dc1.newInstance();
    // Student s= new Student();
    System.out.println(s);
}

@Test
public void testGetField() throws NoSuchFieldException, IllegalAccessException {
    Class c = Student.class;
    // 获取成员变量(getFields()获取所有成员变量,其中返回的是该对象的公开成员变量的数组)
    System.out.println(Arrays.toString(c.getDeclaredFields()));
    // 获取单个成员变量,通过字段名
    System.out.println(c.getDeclaredField("name"));

//     TODO:获取成员变量的作用是进行赋值和取值
//     通过反射暴力获取成员变量的值
    Field school = c.getDeclaredField("school");
    Student s = new Student("张三", 20, "清华大学");
    school.setAccessible(true);//临时将成员变量设置为公开
    // 通过反射进行赋值---field(school)对应的是该对象的成员变量
    school.set(s,"北京大学");//通过这句话对于该对象的这个成员变量进行赋值
    System.out.println(s);
    // 通过反射进行取值
    System.out.println(school.get(s));
}
@Test
public void testGetMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    Class c = Student.class;
    // 获取成员方法(getMethods()获取所有成员方法,其中返回的是该对象的公开成员方法的数组)
    System.out.println(Arrays.toString(c.getMethods()));
    // 获取单个成员方法,通过方法名
    System.out.println(c.getMethod("getAge"));

//     TODO:通过反射获取成员方法的作用是进行方法调用
    Student s = new Student("张三", 20, "清华大学");
    // s.study();为私有的方法不能直接调用
    Method study = c.getDeclaredMethod("study");
    study.setAccessible(true);
    study.invoke(s);//相当于是s.study();
}

反射的应用(通过反射绕过泛型约束)

@Test
public void test() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//     TODO:通过反射绕过相关的泛型约束
    ArrayList<String> list = new ArrayList<>();
    list.add("张三");
    list.add("李四");
    // TODO:由于泛型约束,不能添加其他类型的数据
    // list.add(2.9);
    // list.add(1);

//  获取类对象
    Class c = list.getClass();
//  获取对应的add成员方法
    Method add = c.getDeclaredMethod("add", Object.class);
//  通过反射原理去跳过泛型约束
    add.invoke(list, 2.9);
    add.invoke(list, 1);
    System.out.println(list);
}

Java的框架一般都是通过反射设计一些相关通用功能

对于私有的构造器,方法,成员变量的话要进行,通过类名调用getDeclaredXxx获取到的成员变量,方法,构造器,并将其在要使用的时候设置为公开的

//     TODO:通过反射获取成员方法的作用是进行方法调用
    Student s = new Student("张三", 20, "清华大学");
    // s.study();为私有的方法不能直接调用
    Method study = c.getDeclaredMethod("study");
    study.setAccessible(true);
    study.invoke(s);//相当于是s.study();
//     TODO:获取构造器的作用是创建对象
//  如果构造器是私有的,那么我们就需要通过反射机制来创建对象
    dc1.setAccessible(true);//临时将构造器的权限设置为公开的
    Student s = (Student) dc1.newInstance();
    // Student s= new Student();
    System.out.println(s);
//     TODO:获取成员变量的作用是进行赋值和取值
//     通过反射暴力获取成员变量的值
    Field school = c.getDeclaredField("school");
    Student s = new Student("张三", 20, "清华大学");
    school.setAccessible(true);//临时将成员变量设置为公开
    // 通过反射进行赋值---field(school)对应的是该对象的成员变量
    school.set(s,"北京大学");//通过这句话对于该对象的这个成员变量进行赋值
    System.out.println(s);
    // 通过反射进行取值
    System.out.println(school.get(s));

注解的使用:


自定义注解–》相当于是一个接口继承了Annotation接口

语法格式:

public @interface 注解名{

数据类型 参数名();

}


使用注解的方法

@注解名(…)参数为定义参数名,以及为相关的用法进行赋值

如果说是只有一个value没有定义默认值的话

@注解名(“delete”)—>相当于就是@注解名(value=“delete”)

public @interface A {
    //value为一个特殊的注解属性,如果在只有一个属性时,value可以省略
    String value();
    String name() default "Java";
}

元注解(注解-》注解的注解)

// 表示该注解只能用于类和成员变量上
@Target({ElementType.TYPE,ElementType.FIELD})
// 表示该注解在运行时生效--》一直都有效
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {

}

JUnit注解模拟@MyTest

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class AnnotationDemo {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
    //     TODO:搞清楚注解的应用场景,模拟junit框架
    //     有MyTest的注解就执行

    //  TODO:步骤流程
    //     1、获取类对象
        Class c = AnnotationDemo.class;
    //     2、获取这个类中所有方法
        Method[] methods = c.getDeclaredMethods();
    //     3、遍历所有的方法,判断是否有MyTest注解
        for(Method m:methods){
            if(m.isAnnotationPresent(MyTest.class)){
                // 获取这个注解
                MyTest myTest = m.getDeclaredAnnotation(MyTest.class);
                // 获取注解中的count值
                int count = myTest.count();
                for(int i=0;i<count;i++){
                    m.invoke(new AnnotationDemo());
                }
                // // 有就执行
                // m.invoke(new AnnotationDemo());
            }
        }

    }

    // JUnit的测试方法都是public void
    @MyTest
    public void Test(){
        System.out.println("test");
    }
    public void Test2(){
        System.out.println("test2");
    }
    @MyTest
    public void Test3(){
        System.out.println("test3");
    }
    @MyTest(count = 3)
    public void Test4(){
        System.out.println("test4");
    }
}

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 表示该注解只能用于方法上
@Target({ElementType.METHOD})
// 表示该注解在运行时生效--》一直都有效
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
	int count() default 1;//表示执行的次数
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值