1i javaWeb基础.txt

UP 返回
1.Junit白盒测试
  步骤:
	1 定义一个测试类:被测试的类名Test
	2 定义测试方法:test测试的方法名
	3 给方法加@Test
	4 导入Junit依赖环境

	一般用断言操作来处理结果:
	public class CalculatorTest {
	    @Test
	    public void testAdd(){
	        //定义被测试类
	        Calculator c=new Calculator();
	
	        //调用被测试的方法
	        int result =c.add(1,2);
	
	        //断言
	        Assert.assertEquals(3,result);//前者是期望的结果,后者为实际结果
	    }
	}

	Before和After注解:
	    /**
	     * 初始化方法:
	     * 用于资源申请,所有测试方法在执行前都会先执行该方法
	     */
	    @Before
	    public void init(){
	
	    }
	
	    /**
	     * 释放资源方法:
	     * 在所有测试方法在执行后都会自动执行该方法
	     */
	    @After
	    public void close(){
	
	    }


2.反射(框架设计的灵魂)
  1 将类的各个组成部分封装为其他对象,这就是反射机制
  2 过程:
	Source源代码阶段									Person.java → Person.class,仍然在磁盘上
		↓
		↓	通过类加载器(ClassLoader)
		↓
	Class类对象,将类中的不同成员封装为对象		Class类对象阶段(加载进内存)
	成员变量	Field[] fields
	构造方法	Constructor[] cons
	成员方法	Method[] methods
		↓
		↓	通过类加载器(ClassLoader)
		↓
	Runtime运行时阶段								new Person()		
	
  3 好处
	1 可以在程序运行过程中,操作这些对象
	2 可以解耦,提高程序的可扩展性
  4 Class对象功能
	1 获取成员变量们
	  Field[] getFields()		获取所有public修饰的成员变量
	  Field getField(String name)		获取指定名称的public变量
	  Field[] getDeclaredFields()		获取所有的成员变量,不考虑修饰符
	  Field getDeclaredField(String name)		获取任意指定名称的变量

	  Field的方法:
		Field a=personClass.getField("name");
		Person p=new Person();
		Object value=a.get(p);//获取变量值  !!!!!!!!!!!!!!!!
		a.set(p,"张三");//设置变量值 !!!!!!!!!!!!!!!!

		Field age=personClass.getDeclaredField("age");
            //忽略访问权限修饰符的安全检查
            age.setAccessible(true);//暴力反射 !!!!!!!!!!!!
            Object value2=age.get(p);
            System.out.println(value2);

	 2 获取构造方法
	  Constructor<?>[] getConstructors()
	  Constructor<T> getConstructor(类<?>...parameterTypes)
	  Constructor<T> getDeclaredConstructor(类<?>...parameterTypes)
	  Constructor<T>[] getDeclaredConstructors()

	  Constructor:构造方法
		Constructor constructor1=personClass.getConstructor(String.class,int.class);
            Object person1=constructor1.newInstance("张三",25);//用来创建对象
            Constructor constructor2=personClass.getConstructor();
            Object person2=constructor2.newInstance();
            person2=personClass.newInstance();//如果使用空参数构造方法创建对象,可以简化操作,直接使用Class对象的newInstance
		constructor1.setAccessible(true);//同样可以暴力反射

	  3 获取成员方法们
	  Method[] getMethods()
	  Method getMethod(String name,类<?>... parameterTypes)
	  Method[] getDeclaredMethods()
	  Method getDeclaredMethod(String name,类<?>... parameterTypes)
	
	  Method:方法对象
		Method eatMethod=personClass.getMethod("eat");
            p = new Person();
            eatMethod.invoke(p);//执行方法
            Method eatMethod2=personClass.getMethod("eat",String.class);
            eatMethod.invoke(p,"饭");
		Method[] methods=personClass.getMethods();//获取所有public方法
		for(Method method:methods){
			String name=method.getName();//获取方法名
		}

	  4 获取类名
	  String getName()
  5 利用反射读取配置文件(框架测试)
		public class ReflectTest {
		    public static void main(String[] args) throws Exception{
		        //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);
		    }
		}  
  6 获取Class对象的方式(分别对应三种不同的状态)
	  1 Class.forName("全类名"):将字节码文件加载进内存,返回class对象
		多用于配置文件,将类名定义在配置文件中。读取文件,加载类
	  2 类名.class:通过类名的属性class获取
		多用于参数的传递
	  3 对象.getClass():getClass()方法在Object类中定义了
		多用于对象的获取字节码的方式
		  Class cls1=Class.forName("cn.domain.Person");
	        Class cls2=Person.class;
	        Class cls3=p.getClass();
	  结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个


3.注解
   1 作用
      编写文档:通过代码里标识的注解生成文档【生成doc文档	】			在cmd中使用javadoc AnnoDemo1.java 命令生成文档
      代码分析:对待吗进行分析【使用反射】
      编译检查:让编译器能够实现基本的编译检查【Override】
    2 jdk预定义的一些注解
      @Override:检测被该注解标注的方法是否是继承自父类(接口)的
      @Deprecated:该注解标注的内容已过时		//仍可调用,但调用时方法会被加横线
      @SuppressWarnings:压制警告				//可以写在方法上,但一般写在类上,@SuppressWarnings("all"),表示让编译器忽略一切警告
    3 自定义注解
      1 格式:
         元注解
	   public @interface 注解名称{
			属性列表
		}
	2 本质:注解本质上就是一个接口,该接口默认继承Annotation接口
	   public interface MyAnno extends java.lang.annotation.Annotation{}
	3 属性:接口中的抽象方法
	   	要求:
			1 属性的返回值类型:基本数据类型,String,枚举,注解,以上类型的数组			//不可以是void或者类
			2 定义了属性,在使用时需要给属性赋值。如果定义属性时使用了default关键字给属性默认值,则使用注解时可不赋值
			   如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可
			3 数组赋值时,值使用{}包裹;如果数组只有一个值,则大括号可以省略
				@MyAnno(value=12,per=Per.P1,anno2=@MyAnno2,strs={"abc",""})
	4 元注解:用于描述注解的注解
		@Target:描述注解能够作用的位置		@Target(value={ElementType.TYPE,ElementType.METHOD})
			ElementType取值:
				TYPE:可以作用于类上
				METHOD:可以作用于方法上
				FIELD:可以作用于子成员变量上
		@Retention:描述注解被保留的阶段		@Retention(RetentionPolicy.RUNTIME):当前被描述的注解,或保留到class字节码文件中,并被JVM读取到。一般自定义的注解都取这个值
		@Documented:描述注解是否被抽取到api文档中
		@Inherited:描述注解是否被子类继承
    4 在程序使用(解析)注解:获取注解中定义的属性值
	1 获取注解定义的位置的对象(Class,Method,Field)
	2 获取指定的注解 getAnnotation(Class)
	3 调用注解中的抽象方法获取配置的属性值

		@Pro(className = "cn.domain.Demo1",methodName = "show")		//Pro是自定义的注解,里面有两个属性方法
		public class ReflectAnnoTest {
		
		    public static void main(String[] args) throws Exception{
		
		        //1 解析注解
		        //1.1 获取该类的字节码文件对象
		        Class<ReflectAnnoTest> reflectAnnoTestClass=ReflectAnnoTest.class;
		        //2 获取上面的注解对象
		        //其实就是在内存中生成了一个该注解接口的子类实现对象
		        Pro an=reflectAnnoTestClass.getAnnotation(Pro.class);
		        //3 调用注解对象中定义的抽象方法,获取返回值
		        String className=an.className();								//会自动返回注解赋值时给的值,下同
		        String methodName=an.methodName();
			  //后面的操作同上面反射一样
		    }
		}









DOWN 返回