注解和反射

注解

什么是注解

  • 属于java.annotation包 Annotation是从JDK1.5开始引入的新技术,注解既可以对程序员解释又可以对程序解释

注解与注释的区别

  • 注释:对程序员解释代码信息
  • 注解:对程序和程序员解释代码信息

注解的作用

  1. 注解并不是程序本身,却可以对程序作出解释(与注释(comment)类似)
  2. 可以被其他程序(编译器)读取

注解的格式

  • 注解是以“@注释名”在代码中存在的,还可以添加一些参数 例如:@SuppressWarnings(value=“unchecked”)

注解的应用

  • 可以附加在package、class、method、field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制实现对这些数据的访问
内置注解
  • @Overrlde:定义在java.lang.Override中,此注解只适用于修饰方法,表示一个方法声明打算重写超类中的另一个方法声明

  • @Deprecated:定义在java.lang.Deprecated中.此注解可以用于修饰方法,属性,类。表示不鼓励使用这样的元素.通常是因为它很危险或者存在更好的选择

  • @SuppressWarnings:镇压警告,定义在java.lang.SuppressWarnings中用来抑制编译时的警告信息,与前两个注释有所不同.你需要添加参数才能正确使用。这些参数都是已经定义好了的.我们选择性的使用就好了

    • @SuppressWarnings(“all”)抑制所有类型的警告信息
    • @SuppressWarnings(“unchecked”)抑制单类型的警告信息
    • @SuppressWarnings(value={“unchecked”,“deprecation”})抑制多类型的警告信息
public class Test01 {
	public static void main(String[] args) {
		/**
		 * 知识点:内置注解
		 * 含义:Java给我们提供的注解
		 */

	}
}
class A{
	public void method01() {

	}
}
class B extends A{
	@Override	//表示重写父类方法的注解
	public void method01() {

	}

	@Deprecated	//表示过时(弃用)方法的注解
	public void method02(){

	}

	@SuppressWarnings("all")	//镇压所有警告的注解
	public void method03(){
		String str;
		ArrayList list = new ArrayList();
	}

	@SuppressWarnings("unchecked")	//镇压单类型警告的注解
	public void method04(){
		String str;
		ArrayList list = new ArrayList();
		list.add(123);
		list.add("aaa");
	}
}
元注解
  • 元注解的作用:负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明 这些类型和它们所支持的类在java.lang.annotation包中可以找到 (@Target,@Retention,@Documented,@Inherited )
  1. @Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
  2. @Retention:表示需要要在什么级别保存该注择信息,用于描述注解的生命周期 (SOURCE < CLASS < RUNTIME)
  3. @Document:说明该注解将被包含在javadoc中
  4. @lnherited:说明子类可以继承父类中的该注解
自定义注解

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口

分析:

  • @interface用来声明一个注解,格式:public @interface注解名{定义内容} ,其中的每一个方法实际上是声明了一个配置参数.方法的名称就是参数的名称.
  • 返回值类型就是参数的类型(返回值只能是基本类型、Class、String、enum)
  • 可以通过default来声明参数的默认值
  • 如果只有一个参数成员,一般参数名为value()
@Target({ElementType.TYPE,ElementType.METHOD})	//元注解:标识注解的注解
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
	String str01();
	String str02() default "123";
//	String value();
	String[] value();
}

//@MyAnnotation("123")	//注解中只有一个属性,且名称为value时,可只写值,不写键
//@MyAnnotation({"112233","123"})	//属性为数组,String[] value();传参时要传输组
@MyAnnotation(str01="aaa",value={"ccc"})	//有多个属性时,必须同时写上键与值;若属性有默认值,也可不传值
public class Test01 {

}

反射

Java的反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射的基本使用

反射-获取Class文件对象

配置文件

classpath.properties

classPath=com.dream.reflex01.Student	//类的全路径名

DSClassPath.properties

classPath=com.dream.reflex02.LocalDataSource,com.dream.reflex02.NetworkDataSource,com.dream.reflex02.OtherDataSource	//类的全路径名

DSName.properties

name=本地,网络,其他
public static void main(String[] args) throws Exception {
    /**
    * 需求:获取字节码文件对象
    */
    //获取方式1
    Class<?> c1 = Student.class;

    //获取方式2
    Student stu = new Student();
    Class<?> c2 = stu.getClass();

    //获取方式3
    Properties p = new Properties();
    p.load(Test01.class.getClassLoader().getResourceAsStream("classpath.properties"));
    String classPath = p.getProperty("classPath");
    Class<?> c3 = Class.forName(classPath);

    System.out.println(c1 == c2);   //true
    System.out.println(c1 == c3);   //true

}
反射-操作构造方法

学生类

public class Student extends A{
	
	public String name;
	private char sex;
	private int age;
	private String classId;
	private String id;
	
	public Student() {
	}
	
	private Student(String classId, String id) {
		this.classId = classId;
		this.id = id;
	}

	public Student(String name, char sex, int age, String classId, String id) {
		this.name = name;
		this.sex = sex;
		this.age = age;
		this.classId = classId;
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public char getSex() {
		return sex;
	}

	public void setSex(char sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getClassId() {
		return classId;
	}

	public void setClassId(String classId) {
		this.classId = classId;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}
	
	public void eat() {
		System.out.println(this.name + "吃饭饭");
		sleep();
	}
	
	private void sleep() {
		System.out.println(this.name + "睡觉觉");
	}
	
	@Override
	public String toString() {
		return name + "\t" + sex + "\t" + age + "\t" + classId + "\t" + id;
	}
}

测试类

public static void main(String[] args) throws Exception {
    /**
    * 需求:利用反射机制操作构造方法(在反射中,构造方法、成员方法和成员变量都被当成对象),实例方法即是成员方法。
    */
    //获取Student类的字节码文件对象
    Properties p = new Properties();
    p.load(Test02.class.getClassLoader().getResourceAsStream("classpath.properties"));
    String classPath = p.getProperty("classPath");
    Class<?> c = Class.forName(classPath);

    //获取该类的 public 构造方法
    //Constructor<?>[] constructors = c.getConstructors();
    //for (Constructor<?> constructor : constructors) {
    //    System.out.println(constructor);
    //}

    //获取该类的所有构造方法
    //Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();
    //for (Constructor<?> declaredConstructor : declaredConstructors) {
    //	  System.out.println(declaredConstructor);
    //}

    //利用无参构造创建 Student 对象(1)
    //Student stu = (Student) c.newInstance();
    //System.out.println(stu);
    //利用无参构造创建 Student 对象(2)
    //Constructor<?> constructor = c.getConstructor();
    //Student stu = (Student) constructor.newInstance();
    //System.out.println(stu);

    //利用有参构造创建 Student 对象
    Constructor<?> constructor = c.getDeclaredConstructor(String.class, char.class, int.class, String.class, String.class);
    constructor.setAccessible(true);
    Student stu = (Student) constructor.newInstance("张三", '男', 21, "2107","001");
    System.out.println(stu);

}
反射-操作属性
public static void main(String[] args) throws Exception {
    /**
    * 需求:利用反射机制操作属性
    */
    //获取Student的字节码文件对象
    Properties p = new Properties();
    p.load(Test03.class.getClassLoader().getResourceAsStream("classpath.properties"));
    String classPath = p.getProperty("classPath");
    Class<?> c = Class.forName(classPath);

    //获取本类和父类中公有属性的对象
    //Field[] fields = c.getFields();
    //for (Field field : fields) {
    //    System.out.println(field);
    //}

    //获取本类所有属性的对象
    //Field[] declaredFields = c.getDeclaredFields();
    //for (Field declaredField : declaredFields) {
    //    System.out.println(declaredField);
    //}

    Student stu = new Student("张三", '男', 21, "2017", "001");
    //设置非私有化属性
    Field name = c.getField("name");
    name.set(stu,"李四");

    //设置私有化属性
    Field age = c.getDeclaredField("age");
    age.setAccessible(true);    //设置修改权限
    age.set(stu,23);

    System.out.println(stu);
}
反射-操作方法
public static void main(String[] args) throws Exception {
    /**
    * 需求:利用反射机制操作方法
    */
    //获取Student的字节码文件对象
    Properties p = new Properties();
    p.load(Test03.class.getClassLoader().getResourceAsStream("classpath.properties"));
    String classPath = p.getProperty("classPath");
    Class<?> c = Class.forName(classPath);

    //获取该类及父类的公有方法的对象
    //Method[] methods = c.getMethods();
    //for (Method method : methods) {
    //    System.out.println(method);
    //}

    //获取该类所有方法的对象
    //Method[] declaredMethods = c.getDeclaredMethods();
    //for (Method declaredMethod : declaredMethods) {
    //    System.out.println(declaredMethod);
    //}

    Student stu = new Student("张三", '男', 21, "2107", "001");
    //调用公有方法
    Method setAge = c.getMethod("setAge", int.class);
    setAge.invoke(stu,23);

    //调用私有方法
    Method sleep = c.getDeclaredMethod("sleep");
    sleep.setAccessible(true);
    sleep.invoke(stu);

    System.out.println(stu);
}
反射-操作数组
public static void main(String[] args) {
    /**
    * 需求:利用反射机制操作数组
    */
    //创建String类型的数组
    String[] ss = (String[]) Array.newInstance(String.class,5);

    System.out.println("利用反射来获取数组长度:" + Array.getLength(ss));

    //利用反射设置数组元素
    Array.set(ss,0,"张三");
    Array.set(ss,1,"李四");
    Array.set(ss,2,"王五");
    Array.set(ss,3,"赵六");
    Array.set(ss,4,"虞姬");

    //利用反射遍历数组元素
    for (int i = 0; i < Array.getLength(ss); i++) {
        System.out.println(Array.get(ss,i));
    }
}
反射-操作泛型
public static void main(String[] args) throws Exception {
    /**
    * 需求:利用反射机制操作泛型
    */
    //获取Test06的字节码文件对象
    Class<?> c = Class.forName("com.dream.reflex01.Test06");

    //获取method01的方法对象
    Method method01 = c.getMethod("method01", ArrayList.class, HashMap.class);
    method01.setAccessible(true);
    Type[] genericParameterTypes = method01.getGenericParameterTypes();//获取参数类型
    for (Type t : genericParameterTypes) {
        ParameterizedType type = (ParameterizedType) t;
        //获取参数的泛型的类型
        Type[] actualTypeArguments = type.getActualTypeArguments();
        for (Type typeArgument : actualTypeArguments) {
            System.out.println(typeArgument);
        }
    }

    System.out.println("-----------");

    //获取method02方法对象
    Method method02 = c.getMethod("method02");
    method02.setAccessible(true);
    Type genericReturnType = method02.getGenericReturnType();
    ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
    //获取返回值的泛型类型
    Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
    for (Type type : actualTypeArguments) {
        System.out.println(type);
    }

}

public static void method01(ArrayList<String> list, HashMap<String,Integer> map){

}

public static HashMap<String,Integer> method02(){
    return null;
}

案例

业务与逻辑分离的思想

测试类

public class Test01 {
    /**
     * 需求: 业务与逻辑分离的思想
     */
    public static void main(String[] args) throws Exception {
        Scanner scan = new Scanner(System.in);
        printName();
        System.out.println("请选择数据源:");
        int num = scan.nextInt();

        DataSource dataSource = getDataSource(num);
        dataSource.getData();

        scan.close();
    }

    public static DataSource getDataSource(int num) throws Exception {
        Properties p = new Properties();
        p.load(Test01.class.getClassLoader().getResourceAsStream("DSClassPath.properties"));
        String classPath = p.getProperty("classPath");
        String[] split = classPath.split(",");

        //根据路径创建对象
        Class<?> c = Class.forName(split[num - 1]);
        DataSource dataSource = (DataSource) c.newInstance();
        return dataSource;
    }


    public static void printName() throws Exception {
        Properties p = new Properties();
        p.load(Test01.class.getClassLoader().getResourceAsStream("DSName.properties"));
        String name = p.getProperty("name");
        String[] split = name.split(",");

        StringBuffer sb = new StringBuffer();
        int num = 1;
        for (String s : split) {
            sb.append(num);
            sb.append("-");
            sb.append(s);
            sb.append("  ");
            num++;
        }
        System.out.println(sb);
    }
}

抽象类

public abstract class DataSource {

    public abstract void getData();
}

数据类

public class LocalDataSource extends DataSource {
    @Override
    public void getData() {
        System.out.println("获取本地数据...");
    }
}
public class NetworkDataSource extends DataSource {
    @Override
    public void getData() {
        System.out.println("获取网络数据...");
    }
}

public class OtherDataSource extends  DataSource{
    @Override
    public void getData() {
        System.out.println("其他数据...");
    }
}
反射 + 注解

测试类

public class Test01 {
    public static void main(String[] args) {
        /**
         * 知识点:反射 + 注解 的案例
         */
        Student stu = new Student("张三", '男', 21);

        //获取类上的注解数据
        Class<?> c = stu.getClass();
        TableInfo annotation = c.getAnnotation(TableInfo.class);
        String tableName = annotation.tableName();
        System.out.println(tableName);

        //获取属性上的注解数据
        Field[] declaredFields = c.getDeclaredFields();
        for (Field field : declaredFields) {
            FieldInfo fieldInfo = field.getAnnotation(FieldInfo.class);
            String name = fieldInfo.name();
            String type = fieldInfo.type();
            int length = fieldInfo.length();
            System.out.println(name + "--" + type + "--" + length);
        }

    }
}

自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableInfo {

    String tableName();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldInfo {

    String name();
    String type();
    int length();

}

学生类

@TableInfo(tableName = "db_student")
public class Student{

	@FieldInfo(name = "stu_name",type = "varchar",length = 32)
	private String name;
	@FieldInfo(name = "stu_sex",type = "varchar",length = 32)
	private char sex;
	@FieldInfo(name = "stu_age",type = "int",length = 3)
	private int age;
	
	public Student() {
	}

	public Student(String name, char sex, int age) {
		this.name = name;
		this.sex = sex;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public char getSex() {
		return sex;
	}

	public void setSex(char sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public void eat() {
		System.out.println(this.name + "吃饭饭");
		sleep();
	}
	
	private void sleep() {
		System.out.println(this.name + "睡觉觉");
	}
	
	@Override
	public String toString() {
		return name + "\t" + sex + "\t" + age;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值