注解(Annotation)

  • 注解是JDK5.0开始引入的技术
  • Annotation的作用
    • 不是程序本身,可以对程序做出解释.(这一点与注释(comment)没什么区别)
    • 可以被其他程序(比如:编译器等)读取
  • Annotation的格式
    • 注解是以”@注释名”在代码中存在的,还可以添加一些参数值,例如:@SuppressWarnings(value=”unchecked”)
  • Annotation在哪里使用

    • 可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问

      1. public class Application {
      2. @Override
      3. public String toString() {
      4. return super.toString();
      5. }
      6. public static void main() {
      7. }
      8. }

      内置注解

  • @Override:定义在java.lang.Override中,此注解只适用于修饰方法,表示一个声明打算重写超类中的另一个方法声明

  • @Deprecated: 定义在java.lang.Deprecated中,此注释可用于修饰方法,属性,类表示不鼓励程序员使用这样的元素,通常因为它很危险或者存在更好的选择
  • @SuppressWarning: 定义在java.lang.SuppressWarning中,用来抑制编译时的警告信息
    • 与前两个注释有所不同。你需要添加一个参数才能正确使用,这些参数都是已经定义好了的,我们选择性的使用就好了
      • @SuppressWarning(“all”)
      • @SuppressWarning(“unchecked”)
      • @SuppressWarning(value={“unchecked”, “deprecation”})
      • 等等……

image.png

元注解

  • 元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明
  • 这些类型和它们所支持的类在java.lang.annotation包中可以找到。(@Target, @Retention, @Document, @Inherited)
    • @Target : 用来描述注解的使用范围(即被描述的注解可以用在什么地方)
    • @Retention: 表示需要在什么级别保存该注解信息,用于描述注解的声明周期
      • (SOURCE < CLASS < RUNTIME)
    • @Document: 说明该注解将被包含在javadoc中
    • @Inherited: 说明子类可以继承父类中的注解

image.png

自定义注解

  • 使用@interface自定义注解时,自动继承了java.lang.Annotation接口
  • 分析:
    • @interface用来声明一个注解,格式:public@ interface注解名{ 定义内容 }
    • 其中的每一个方法实际上是声明了一个配置参数
    • 方法的名称就是参数的名称
    • 返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum)
    • 可以用过default来声明参数的默认值
    • 如果只有一个参数成员,一般参数名为value
    • 注解元素必须要有值,我们定义注解时,经常使用空字符串、0作为默认值

image.png

反射(Java Reflection)

  • Reflection(反射)是java被视为动态语言的关键,反射机制允许程序在执行期间借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
    1. - Class c = Class.forName("java.lang.String")
  • 加载完类之后,在内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构。所以,我们形象称之为反射

Java基础(第六篇) - 图4

Java反射机制研究及应用

  1. Java反射机制提供的功能
  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时获取泛型信息
  • 在运行时调用任意一个对象的成员变量和方法
  • 在运行时处理注解
  • 生成动态代理
  • ………………..
  1. 优缺点
  • 有点:可以实现动态创建对象和编译,体现出很大的灵活性
  • 缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于执行相同的操作
  1. 反射相关的主要API
  • java.lang.Class:代表一个类
  • java.lang.reflect.Method: 代表类的方法
  • java.lang.reflect.Field: 代表类的成员变量
  • java.lang.reflect.Constructor: 代表类的构造器
  • ……………..

Java基础(第六篇) - 图5

  1. package com.xy;
  2. public class Test06 {
  3. public static void main(String[] args) throws ClassNotFoundException {
  4. Person person = new Student();
  5. System.out.println("这个人是:" + person.name);
  6. // 方式一: 通过对象获得
  7. Class c1 = person.getClass();
  8. // 方式二: 用forName获得
  9. Class c2 = Class.forName("com.xy.Student");
  10. // 方式三:通过类名.class 获得
  11. Class c3 = Student.class;
  12. // 方式四: 基本类型的包装类都有一个Type属性
  13. Class c4 = Integer.TYPE;
  14. // 获得父类的类型
  15. Class c5 = c1.getSuperclass();
  16. System.out.println(c1.hashCode());
  17. System.out.println(c2.hashCode());
  18. System.out.println(c3.hashCode());
  19. System.out.println(c4);
  20. System.out.println(c5);
  21. }
  22. }
  23. class Person {
  24. public String name;
  25. public Person() {
  26. }
  27. public Person(String name) {
  28. this.name = name;
  29. }
  30. @Override
  31. public String toString() {
  32. return "Person{" + "name+'" + name + '\'' + '}';
  33. }
  34. }
  35. class Student extends Person {
  36. public Student() {
  37. this.name = "学生";
  38. }
  39. }
  40. class Teacher extends Person {
  41. public Teacher() {
  42. this.name = "老师";
  43. }
  44. }

那些类有Class对象

  • class: 外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
  • interface: 接口
  • []: 数组
  • enum:枚举
  • annotation:注解@interface
  • primitive type: 基本数据类型
  • void ```java package com.xy;

import java.lang.annotation.ElementType;

public class Test05 { public static void main(String[] args) { Class c1 = Object.class; // 类 Class c2 = Comparable.class; // 接口 Class c3 = String[].class;// 一维数组 Class c4 = int[][].class; // 二维数组 Class c5 = Override.class; // 注解 Class c6 = ElementType.class; // 枚举 Class c7 = Integer.class; // 基本数据类型 Class c8 = void.class; // void Class c9 = Class.class; // Class System.out.println(c1); System.out.println(c2); System.out.println(c3); System.out.println(c4); System.out.println(c5); System.out.println(c6); System.out.println(c7); System.out.println(c8); System.out.println(c9);

  1. int[] a = new int[10];
  2. int[] b = new int[100];
  3. System.out.println(a.getClass().hashCode());
  4. System.out.println(b.getClass().hashCode());
  5. }

}

  1. <a name="VEdne"></a>
  2. ### Java内存分析
  3. ![](https://cdn.nlark.com/yuque/0/2022/jpeg/13002623/1650809413834-1ae9e7d2-e0b3-42dd-a147-876b846ebfd3.jpeg)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/13002623/1650809576275-0d82dac4-5ab7-4b96-a8df-9955cac9d7df.png#clientId=u8872cbe5-a13a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=889&id=u9cac1664&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1334&originWidth=2517&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1154251&status=done&style=none&taskId=u285dee12-a91a-4bd7-a5ce-9aa2b0be90e&title=&width=1678)
  4. <a name="ksPib"></a>
  5. ### 反向操作注解
  6. - getAnnotations
  7. - getAnnotation
  8. ```java
  9. package com.xy;
  10. import java.lang.annotation.*;
  11. import java.lang.reflect.Field;
  12. public class Test01 {
  13. public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
  14. // 获得类的注解
  15. Class c1 = App.class;
  16. Annotation[] annotations = c1.getAnnotations();
  17. for(Annotation annotation: annotations) {
  18. System.out.println(annotation);
  19. }
  20. // 获得类的注解的指定值
  21. Table table = (Table)c1.getAnnotation(Table.class);
  22. String value = table.value();
  23. System.out.println(value);
  24. // 获得类指定的注解
  25. Field f = c1.getDeclaredField("name");
  26. FieldA annotation = f.getAnnotation(FieldA.class);
  27. System.out.println(annotation.columnName());
  28. }
  29. }
  30. @Table("db_app")
  31. class App {
  32. @FieldA(columnName = "db_app_id", type = "int", length = 10)
  33. private int id;
  34. @FieldA(columnName = "db_app_age", type = "int", length = 10)
  35. private int age;
  36. @FieldA(columnName = "db_app_name", type = "varchar", length = 10)
  37. private String name;
  38. public App() {
  39. }
  40. public App(int id, int age, String name) {
  41. this.id = id;
  42. this.age = age;
  43. this.name = name;
  44. }
  45. public int getId() {
  46. return id;
  47. }
  48. public void setId(int id) {
  49. this.id = id;
  50. }
  51. public int getAge() {
  52. return age;
  53. }
  54. public void setAge(int age) {
  55. this.age = age;
  56. }
  57. public String getName() {
  58. return name;
  59. }
  60. public void setName(String name) {
  61. this.name = name;
  62. }
  63. }
  64. // 类名的注解
  65. @Target(ElementType.TYPE)
  66. @Retention(RetentionPolicy.RUNTIME)
  67. @interface Table {
  68. String value();
  69. }
  70. // 属性的注解
  71. @Target(ElementType.FIELD)
  72. @Retention(RetentionPolicy.RUNTIME)
  73. @interface FieldA {
  74. String columnName();
  75. String type();
  76. int length();
  77. }