反射与注解

时间:2020-06-18 14:59:16   收藏:0   阅读:62

一、Junit单元测试

测试分类

测试步骤

public class Calculator {
    public int add (int a , int b){
        //int i = 3/0;
        return a - b;
    }

    public int sub (int a , int b){
        return a - b;
    }
}
public class CalculatorTest {
    /**
     * 初始化方法:
     *  用于资源申请,所有测试方法在执行之前都会先执行该方法
     */
    @Before
    public void init(){
        System.out.println("init...");
    }
    /**
     * 释放资源方法:
     *  在所有测试方法执行完后,都会自动执行该方法
     */
    @After
    public void close(){
        System.out.println("close...");
    }
    /**
     * 测试add方法
     */
    @Test
    public void testAdd(){
       // System.out.println("我被执行了");
        //1.创建计算器对象
        System.out.println("testAdd...");
        Calculator c  = new Calculator();
        //2.调用add方法
        int result = c.add(1, 2);
        //System.out.println(result);

        //3.断言  我断言这个结果是3
        Assert.assertEquals(3,result);

    }
    @Test
    public void testSub(){
        //1.创建计算器对象
        Calculator c  = new Calculator();
        int result = c.sub(1, 2);
        System.out.println("testSub....");
        Assert.assertEquals(-1,result);
    }
}

二、反射

反射是框架设计的灵魂

反射是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法

Class c = Class.forName("java.lang.String")

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,因此我们形象的称之为:反射
技术分享图片

1. 使用的前提条件

必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)

2. 概述

JAVA反射机制

可以这样理解:

技术分享图片

2. Class类

Java的Class类是java反射机制的基础,通过Class类我们可以获得关于一个类的相关信息

Java.lang.Class是一个比较特殊的类,它用于封装被装入到JVM中的类(包括类和接口)的信息。当一个类或接口被装入的JVM时便会产生一个与之关联的java.lang.Class对象,可以通过这个Class对象对被装入类的详细信息进行访问。

虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。

一个类被加载到内存并供我们使用需要经历如下三个阶段

所有的类都是在对其第一次使用时,动态加载到JVM中的(懒加载)。当程序创建第一个对类的静态成员的引用时,就会加载这个类。使用new创建类对象的时候也会被当作对类的静态成员的引用。因此java程序程序在它开始运行之前并非被完全加载,其各个类都是在必需时才加载的。这一点与许多传统语言都不同。动态加载使能的行为,在诸如C++这样的静态加载语言中是很难或者根本不可能复制的

在类加载阶段,类加载器首先检查这个类的Class对象是否已经被加载。如果尚未加载,默认的类加载器就会根据类的全限定名查找.class文件。在这个类的字节码被加载时,它们会接受验证,以确保其没有被破坏,并且不包含不良java代码。一旦某个类的Class对象被载入内存,我们就可以它来创建这个类的所有对象

3. 获取Class对象

如果我们动态获取到这些信息,则需要依靠 Class 对象。Class 类对象将一个类的方法、变量等信息告诉运行的程序

三种方式常用第一种,一个字符串可以传入也可写在配置文件中等多种方法。第二种需要导入类的包,依赖太强,不导包就抛编译错误。第三种有对象可不用反射。

技术分享图片

package cn.itcast.domain;

public class Person {
    private String name;
    private int age;

    public String a;
    protected String b;
    String c;
    private String d;

	//省略getter、setter方法(name,age),构造方法(name,age),toString方法(所有)

    public void eat(){
        System.out.println("eat...");
    }

    public void eat(String food){
        System.out.println("eat..."+food);
    }
}
public class ReflectDemo1 {

    /**		获取Class对象的方式:
            1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
            2. 类名.class:通过类名的属性class获取
            3. 对象.getClass():getClass()方法在Object类中定义着。*/
    public static void main(String[] args) throws Exception {

        //1.Class.forName("全类名"),即包名.类名
        Class cls1 = Class.forName("cn.itcast.domain.Person");
        System.out.println(cls1);
        //2.类名.class
        Class cls2 = Person.class;
        System.out.println(cls2);
        //3.对象.getClass()
        Person p = new Person();
        Class cls3 = p.getClass();
        System.out.println(cls3);

        //== 比较三个对象
        System.out.println(cls1 == cls2);//true
        System.out.println(cls1 == cls3);//true

        Class c = Student.class;
        System.out.println(c == cls1);
    }
}

4. Class对象功能

获取功能

通过Class对象可以获取某个类中的构造方法、成员变量、成员方法;并访问成员

获取成员变量并调用

获取构造方法

获取成员方法

获取全类名

三、案例

需求

实现

  1. 配置文件
  2. 反射

步骤

  1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
  2. 在程序中加载读取配置文件
  3. 使用反射技术来加载类文件进内存
  4. 创建对象
  5. 执行方法
public class Student {


    public void sleep(){
        System.out.println("sleep...");
    }
}

配置文件:新建一个file文件pro.properties

className =itcast.domain.Person	//包名.类名
methodName = eat
import cn.itcast.domain.Person;
import cn.itcast.domain.Student;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 框架类
 */
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //可以创建任意类的对象,可以执行任意方法

        /*
            前提:不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法
         */
      /*  Person p = new Person();
        p.eat();*/
/*
        Student stu = new Student();
        stu.sleep();*/

        //1.加载配置文件
        //1.1创建Properties对象
        Properties pro = new Properties();
        //1.2加载配置文件,转换为一个集合
        //1.2.1获取class目录下的配置文件
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        pro.load(is);

        //2.获取配置文件中定义的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");


        //3.加载该类进内存
        Class cls = Class.forName(className);
        //4.创建对象
        Object obj = cls.newInstance();
        //5.获取方法对象
        Method method = cls.getMethod(methodName);
        //6.执行方法
        method.invoke(obj);


    }
}

四、注解

概念

定义

基本内置注解

//测试内置注解
import java.util.ArrayList;
import java.util.List;
//所有类默认继承Object类
public class Test1 extends Object {
	//@Override 表示方法重写
	@Override
	public String toString() {
		return super.toString();
        } 
    //方法过时了, 不建议使用,可能存在问题,并不是不能使用
    @Deprecated
    public static void stop(){
        System.out.println("测试 @Deprecated");
    } 
	//@SuppressWarnings 抑制警告 , 可以传参数

	@SuppressWarnings("all")
public void sw(){
	List list = new ArrayList();
} 
    public static void main(String[] args) {
		stop();
	}
}

元注解

自定义注解

在程序使用(解析)注解

参考博客:https://blog.csdn.net/sinat_38259539/java/article/details/71799078

原文:https://www.cnblogs.com/lf-637/p/13157524.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!