本来这一篇是接在上一篇后面的,但是晚上写到一半有事出去了,故而分开了,
这一篇用到了jar包有:mysql-connector-java-5.0.8-bin.jar
7,注解:
7.1 概述:jdk5.0的新特性
包括有:泛型,自动装箱,自动拆箱,静态导入,可变参数,增强for循环,枚举等(快去把老版本的jdk升级吧)
7.1.1 注解不是注释
注释是给程序员看代码用的,注解是代码中的特殊标记,可以看做是替代配置文件的选择,本身意义不大,但是可以通过注解+反射组合告诉类该如何运行
7.1.2 写法:
@注解的名称 (通过eclipse自动生成的方法重写中就包含了注解)
适用范围:既可以在类上面,也可以在方法上面
7.2 jdk里面的三个注解
①@Override :限定重写父类方法,该方法必须遵循方法重写的定义,只能用于方法
下面两个注解都不影响代码的执行
②@Deprecated:用于表示某个元素(类,方法)已过时(参考某date类,各种过时的方法)
③@SuppressWarnings:抑制编译器警告@SuppressWarnings(“all”)(去掉所有代码中的小黄线(未被使用的对象,变量之类))
7.3 自定义注解
①定义方式:@interface 注解的名称{ }
②注解的属性,在注解中添加: 数据类型 属性名称();
在使用位置@自定义注解名(属性名=属性值,属性名=属性值)
③常见错误:The annotation @MyAnno must define the attribute date;
Invalid type Date for the annotation attribute MyAnno.date; only primitive type, String, Class, annotation, enumeration are permitted or 1-dimensional arrays thereof
定义属性为date类型报错,根据错误信息可知:只能允许基本数据类型,String,Class,枚举,注解,一维数组(只能包含这些类型的);
使用方式:写在方法或类上
特殊属性value
①当自定义注解中存在一个属性名称为value的时候,String value(); 在写注解的时候可以省略名字,直接写具体的值
7.3.1 元注解(也叫修饰注解)
①它是修饰注解的注解
@Retention:修饰注解的使用范围,自定义一个注解,修饰注解的使用范围
包含的值:RetentionPolicy.CLASS:编译器把注解记录在CLASS文件中,当运行JAVA程序时,JVM不会保留注解,这是默认值
RetentionPolicy.RUNTIME:编译器把注解记录在CLASS文件中,当运行JAVA程序时,JVM会保留注解,程序可以通过反射获取注解
RetentionPolicy.SOURCE:编译器直接丢弃这种策略的注解
@Target:指定注解用于修饰类的哪个成员
@Target包含了一个value,类型为ElementType的成员变量
@Target({ElementType.METHOD.ElementType.PARAMETER})
@Document: 用于指定该元Annotation修饰的Annotation类被javadoc工具提取成文档
@Inheriter:这个类是否有继承性,子类是否需要继承父类的注解
7.4 反射+注解的练习
7.4.0单元测试简介:junit
测试一个类中的方法,使用注解的方式进行测试@Test
这里需要用一个jar包, org.junit.Test;可以快捷导入
然后通过右键run as-----junit test
运行以后可以看到JUNIT视图,有一个绿色条进度条,表示测试通过了
(点击方法名,可以单独测试一个方法,在类中方法外右击,可以测试所有方法)
@Ignore,批量测试中忽略该方法
当出现红棕色的进度条,代表测试的方法中有问题,点击对应的方法可以找到出现BUG的地方
7.4.1 模拟单元测试的效果
模拟步骤:
//实现效果,在类中带注解的方法都执行
/*
* 实现步骤:
* 1,得到类的字节码文件
* 三种方式:
* 类名.class
* 对象名.getClass()
* Class.forName("全类名")
* 2,得到被测试类中所有的方法 Class类中的 getMethods(),返回的是一个Method数组
* 3,遍历数组,得到类中的每个方法
* 4,判断方法上是否有注解
* Boolean 在Method的父类中有一个方法 isAnnotationPresent(Class<? extends Annotation> annotationClass)
* 5,如果有注解,就让方法执行即可
* Method中的 invoke(对象,方法中的参数);
*/
7.4.2 使用反射获取注解中的属性值
练习:通过反射获取jdbc的操作
步骤:
第一步:创建注解,注解中定义操作数据库的相关属性
第二步:得到类的字节码文件,得到带注解的方法
Method getMethod(方法名,方法里面的参数列表对应的字节码文件)
第三步:得到方法上的注解
<T extends Annotation>T getAnnotation(Class<T> annotation)
第四步:得到对应的属性,进行jdbc操作
附录:不使用反射的实现代码
package com.zzx.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import sun.print.resources.serviceui; //不使用反射之前的操作 public class TestJDBC01 { public static void main(String[] args) { selecttest1(); } //查询数据库 public static void selecttest1(){ Connection conn = null; Statement state = null; ResultSet rs = null; try { //1,加载驱动 Class.forName("com.mysql.jdbc.Driver"); //2,创建链接 conn = DriverManager.getConnection("jdbc:mysql:///zzx02","root","747474"); //3,创建sql语句 String sql = "select * from test1"; //4,执行sql state = conn.createStatement(); rs = state.executeQuery(sql); while(rs.next()){ String id = rs.getString("id"); String sex = rs.getString("sex"); System.out.println(id + ":" + sex); } } catch (Exception e) { e.printStackTrace(); }finally{ if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } rs=null; if(state!=null){ try { state.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } state=null; if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } conn=null; } } }
//使用注解+反射之后获取配置信息
package com.zzx.jdbc; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; //这个类测试注解获取相关配置属性的效果 public class TestJDBC02 { public static void main(String[] args) { select(); } @JDBCAnno(drivername="com.mysql.jdbc.Driver",url="jdbc:mysql:///zzx02",username="root",password="747474") //这样写不如直接写配置文件,但是这里是为了练习 public static void select(){ //1,得到类的Class文件 Class clazz = TestJDBC02.class; //2,得到带注解的方法 Method m1 = null; try { m1 = clazz.getMethod("select"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } //3,得到方法上的注解 JDBCAnno ja = m1.getAnnotation(JDBCAnno.class); //4,得到注解中的属性值 String drivername =ja.drivername(); String url = ja.url(); String username = ja.username(); String password = ja.password(); Connection conn = null; Statement state = null; ResultSet rs = null; try { //1,加载驱动 Class.forName(drivername); //2,创建链接 conn = DriverManager.getConnection(url,username,password); //3,创建sql语句 String sql = "select * from test1"; //4,执行sql state = conn.createStatement(); rs = state.executeQuery(sql); while(rs.next()){ String id = rs.getString("id"); String sex = rs.getString("sex"); System.out.println(id + ":" + sex); } } catch (Exception e) { e.printStackTrace(); }finally{ if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } rs=null; if(state!=null){ try { state.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } state=null; if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } conn=null; } } }
自定义注解类
package com.zzx.jdbc; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; //这个注解用来实现JDBC 反射操作 @Retention(RetentionPolicy.RUNTIME) public @interface JDBCAnno { //定义属性 String drivername(); String url(); String username(); String password(); }