单元测试_反射_注解_动态代理

单元测试

   含义:最小的功能单元编写测试代码(Java的方法)

​ 优点: 一键执行;生测试报告(绿色正常,红色报错);执行不影响其他的测试方法

 怎么做: 1.使用Junit4.jar导入到库中;2.@Test注解(1.公开的、无参数、无返回值;2.主要在方法上注解)3.Assert 断言 判断  						方法是否有问题

反射

​ 含义:对于任意一个Class类,在"运行的时候"都可以得到这个类的全部成分如Constructor Field Method

​ 优点: Java语言的反射机制:动态获取类信息和动态调用类中成分的能力

​ 怎么做:获取Class类对象

//        1.通过类名.Class
        Class<Student> studentClass = Student.class;
        System.out.println(studentClass); //Student.class

//        2.通过类的静态方法:forName(全限名:包名+类名)
        Class<?> forName = Class.forName("com.lyi.d2_reflect_create.Student");
        System.out.println(forName);

//        3.通过对象自身的方法 对象.getClass
        Student student = new Student("张三");
        System.out.println(student.getClass());
//     class com.lyi.d2_reflect_create.Student

​ 获取类构造器对象

获取所有公共构造函数
        // 1.获取Class对象 
        Class<?> aClass = Student.class;
        // 2.包含一个数组 Constructor对象反射由此表示的类的所有公共构造函数
        Constructor<?>[] constructors = aClass.getDeclaredConstructors();
        // 3.遍历所有的公共的构造函数
        for (Constructor<?> constructor : constructors) {
            System.out.println("构造器名称:" + constructor.getName() +
                    ";构造器的参数个数:" + constructor.getParameterCount());
 获取指定的构造函数
        //通过有参构造器获取对象
		Class<Student> studentClass2 = Student.class;
         //  parameterTypes – 参数数组  返回值:具有指定参数列表的构造函数的Constructor对象
		Constructor<Student> cons2 = studentClass2.getDeclaredConstructor(String.class,int.class);
		System.out.println(cons2.getName()+"\t" + cons2.getParameterCount());
		//initargs – 作为参数传递给构造函数调用的对象数组  返回值:通过调用此对象表示的构造函数创建的新对象
		Student student1 = cons2.newInstance("张三"   ,500);

​ 获取成员变量


//获取所有成员变量
		Class<Student> studentClass = Student.class;
         //返回值 表示该类的所有声明字段的Field对象数组
		for (Field field : studentClass.getDeclaredFields()) {
			System.out.println(field.getName()+ "\t" + field.getType());
		}

//获得指定成员变量
		Class<Student> studentClass1 = Student.class;
		//name – 字段的名称  返回值此类中指定字段的Field对象 
		Field declaredField = studentClass1.getDeclaredField("age");
		System.out.println(declaredField.getName()+ "\t" + declaredField.getType());

//给成员变量赋值和取值
		Class<Student> studentClass = Student.class;
		Field ageF = studentClass.getDeclaredField("age");
		// 暴力打开私有成员的变量的访问大小
		ageF.setAccessible(true);
		Student student = new Student();
		//	设置成员变量的值
		//参数:obj - 应修改其字段的对像 value – 被修改的obj字段的新值
		ageF.set(student,20);
		//获得成员变量的值
		System.out.println(ageF.get(student));

​ 获取成员方法

//通过getDeclaredMethods获取所有方法
		Class<Dog> dogClass = Dog.class;
       //返回Method对象的数组,表示该类的所有声明的方法
		for (Method declaredMethod : dogClass.getDeclaredMethods()) {
              
			System.out.println(declaredMethod.getName() + ": " + declaredMethod.getParameterCount());
		} 
//通过getDeclaredMethod获取指定方法
		Class<Dog> dogClass = Dog.class;
       	//name – 方法的名称  parameterTypes – 参数数组回报: 与指定名称和参数匹配的此类方法的Method对象
		Method method1 = dogClass.getDeclaredMethod("buy", String.class);
		method1.setAccessible(true);
		Dog dog1 = new Dog();
		//obj – 调用底层方法的对象 args – 用于方法调用的参数  回报:使用参数args在obj上调度此对象表示的方法的结果
		Object result2 = method1.invoke(dog1, "衣服");
		System.out.println(result2);

绕过编译阶段给集合添加数据

//ArrayList 在编译阶段 移除泛型
		ArrayList<Integer> list = new ArrayList<Integer>();
		ArrayList<String> list2 = new ArrayList<String>();
		System.out.println(list.getClass()==list2.getClass());

		ArrayList<Integer> list3 = new ArrayList<Integer>();
		list3.add(1);
		list3.add(2);

         //获取class对象
		Class<? extends ArrayList> genericityClass = list3.getClass();
         // public boolean add(E e) 利用反射获取这个add方法 和 成员变量
		Method add = genericityClass.getDeclaredMethod("add", Object.class);
		boolean rs = (boolean) add.invoke(list3, "白马");
		System.out.println(rs);

利用反射,手动编译动态方法

//把代码放在try()里面 可以不用关闭流操作
		try (
             FileOutputStream fos = new FileOutputStream("day04-junit-reflect-annotation-proxy-				        			  app/src/testOverride.txt",true);
             PrintStream printStream = new PrintStream(fos))
		{
			//	1.定义一个方法,可以接收任意类的对象
			Class<Object> objectClass = (Class<Object>) obj.getClass();

			printStream.println("=============="+ objectClass.getSimpleName() +"==============");
			//	2.每次收到一个对象后,需要解析这个对象的全部成员变量名称
			for (Field declaredField : objectClass.getDeclaredFields()) {
				declaredField.setAccessible(true);
				// 3.遍历成员变量信息,然后提取本成员变量在对象中的具体值
				Object fieldName = declaredField.getName();
				Object fieldValue = declaredField.get(obj);
				System.out.println(fieldName + "=" + fieldValue);
				//4.存入成员变量名称和值到文件中去即可
				printStream.println(fieldName + "=" + fieldValue);
			}

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

注解

含义: 标注,Jdk1.5的注释机制

作用: 对Java中的类、方法、成员变量作标记,然后做特殊处理

怎么做:

自定义注解

格式:

public @interface 注解名称{
	public 属性类型 属性名() default;
}
元注解

​ 含义:注解加注解

​ 怎么做:

@Retention(RetentionPolicy.RUNTIME)
//指示注释类型适用的上下文。 只能在方法和类的类型上也就是class对象
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface  Book{
	public   String value();
	public double price() default 100.0;
	public String[] authors() ;
}
注解的解析:

​ 含义:是否存在注解,存在就解析出内容

怎么做:

//获取注解在类上面的数据           
             // 1.先得到类对象
			Class<BookStore> bookStoreClass = BookStore.class;
			// 2.判断这个类上面是否有注解类  参数: annotationClass——注解类型对应的Class对象
			if (bookStoreClass.isAnnotationPresent(Book.class)) {
				// 3.获取该注解对象 参数: annotationClass——注解类型对应的Class对象 
				Book declaredAnnotation = bookStoreClass.getDeclaredAnnotation(Book.class);
				System.out.println(declaredAnnotation.value());
				System.out.println(declaredAnnotation.price());
				System.out.println(Arrays.toString(declaredAnnotation.authors()));
//获取注解在方法上面的数据
         // 1.先得到类对象
		Class<BookStore> bookStoreClass2 = BookStore.class;
		// 1.1 获取这个类的下面指定的方法
		Method run = bookStoreClass2.getDeclaredMethod("run");
		// 2.判断这个类上面是否有注解类
		if (run.isAnnotationPresent(Book.class)) {
			// 3.获取该注解对象
			Book declaredAnnotation = run.getDeclaredAnnotation(Book.class);
			System.out.println(declaredAnnotation.value());
			System.out.println(declaredAnnotation.price());
			System.out.println(Arrays.toString(declaredAnnotation.authors()));
 //执行注解的方法
         AnnotationDemo2 demo = new AnnotationDemo2();
		Class aClass = AnnotationDemo2.class;
		Method[]  methods = aClass.getDeclaredMethods();
		for (Method method : methods) {
			if(method.isAnnotationPresent(Mytest.class)) {
                // name-->对象     反射 对象.方法 
				method.invoke(demo);
			}
		}

动态代理

代理:某些情况下对象会找一些代理对象,替他完成额外的工作,如明星(经纪人)

  1. 先有接口Sing这个动作

  2. 对象实现这个接口,并且重写这个方法的内容

  3. 通过Proxy.newProxyInstance(ClassLoader,Interface,Handle),得到对象的代理对象

  4. 通过代理方法获取代理类,然后调用接口里面的方法

    image-20220618120131820
    //关键代理类方法
    
    		/**
    		 * Object newProxyInstance(ClassLoader loader,
    		 *       Class<?>[] interfaces,
    		 *       InvocationHandler h)
    		 *
    		 loader – 定义代理类的类加载器
    		 interfaces – 代理类要实现的接口列表
    		 h - 将方法调用分派到的调用处理程序
    		 */
    		return (Skill) Proxy.newProxyInstance(star.getClass().getClassLoader(),
    				star.getClass().getInterfaces(), new InvocationHandler() {
                        //method – Method实例对应于代理实例上调用的接口方法。
    				  //obj – 调用底层方法的对象 args – 一个对象数组,其中包含在代理实例上的方法调用中传递的参数值
    					@Override
    					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    						System.out.println("收定金");
    						Object rs = method.invoke(star);
    						System.out.println("收尾款,并且把杨接回来!!");
    						return rs;
    					}
    				});
    	}
    

    手动编写动态代理练习

    	//核心动态代理编码
      public static <T> T getProxyUserService(T obj) {
    		return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
    				obj.getClass().getInterfaces(),
    				new InvocationHandler() {
    					@Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            long startTime = System.currentTimeMillis();
                            Object rs = method.invoke(obj, args);
                            long endTime = System.currentTimeMillis();
    				      System.out.println(method.getName() + "耗时:" + 
                                       (endTime - startTime)/1000 + " seconds");
    						return rs;
    					}
    				});
    

    作用

    • 方法增强,提高复用
    • 简化编程工作,提高效率,可扩展性
    • 可以为被代理对象的所有方法做代理
    • 支持任意接口类型的实现类做代理
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值