概述
Annotation的作用
- 不是程序本身,可以对程序作出结束(与注释comment无异)
- 可以备其他程序(比如编译器)读取
Annotation的格式
- 注解是以
@注释名
在代码中存在的,还可以添加一些参数值,例如@SuppressWarnings(value = “unchecked”)
Annotation在哪里使用?
- 可以附加在package,class,method,field上面,相当于添加额外的辅助信息,可以通过反射机制编程实现对这些元数据的访问
内置注解
-
@Override
定义在java.lang.Override
中,此注释只适用于修辞手法,表示一个方法声明打算重写超类中的另一个方法声明 -
@Deprecated
定义在java.lang.Deprecated
中,此注释可以用于修饰方法、属性、类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择 -
@SuppressWarnings
定义在java.lang.SuppressWarnings
中,用来抑制编译时的警告信息,与前两个有所不同的是需要添加一个参数才能正常使用,这些参数都是定义好的@SuppressWarnings("all") @SuppressWarnings("unchecked") @SuppressWarnings(value = {"unchecked", "deprecation"}) ...
元注解
元注解的作用就是负责注解其他注解,java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明
☆ @Target //用于描述注解的适用范围
☆ @Retention //表示在什么级别保存该注释信息,用于描述注解的生命周期(source < class < RUNTIME)
@Document // 说明该注解将被包含在javadoc中
@Inherited // 说明子类可以继承父类中的该注解
自定义注解
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
分析:
- @interface用来声明一个注解,格式
public @inteface 注解名 { content }
- 其中的每一个方法实际上是声明了一个配置参数
- 方法的名称就是参数的名称
- 返回值类型就是参数的类型(返回值只能是基本类型 class、String、 enum)
- 可以通过default来声明参数的默认值
- 如果只有一个参数成员,一般参数名为value
- 注解元素必须要有值,我们定义注解元素时,经常使用空字符串、0作为默认值
package com.company.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 自定义注解
public class test1 {
// 注解可以显示赋值 如果没有默认值,就必须给注解赋值
@MyAnnotation(name = "oho", age = 19)
public void test(){
}
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
// 注解的参数: 参数类型 + 参数名();
// String value(); 此时上面的引用可以不需要 value = "xxx"
String name() default "";
int age() default 0;
int id() default -1;// 如果默认值为-1,代表不存在
String[] schoold() default "TshinghuaU";
}
反射机制
package com.company.annotation;
public class reflection {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.company.annotation.User");
System.out.println(c1);
Class c2 = Class.forName("com.company.annotation.User");
Class c3 = Class.forName("com.company.annotation.User");
Class c4 = Class.forName("com.company.annotation.User");
// 一个类在内存中只有一个class对象
// 一个类被加载后,类的整个结构都会被封装在class对象中
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
}
}
// 实体类 : pojo, entity
class User{
private String name;
private int id;
private int age;
public User() {
}
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}
// 运行结果
/*
class com.company.annotation.User
284720968
284720968
284720968
*/
Class 类
获取Class类的实例
package com.company.annotation;
public class refClass {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("this is :" + person.name);
// 方式一: 通过对象获得
Class c1 = person.getClass();
System.out.println(c1);
// 方式二: forname获得
Class c2 = Class.forName("com.company.annotation.Student");
System.out.println(c2);
// 方式三:通过类名.class获得
Class c3 = Student.class;
System.out.println(c3);
// 方法四 :基本内置类型的包装类都有一个Type属性
Class c4 = Integer.TYPE;
System.out.println(c4);
// 获得父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
class Person{
String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student(){
this.name = "Stu";
}
}class Teacher extends Person{
public Teacher(){
this.name = "Teac";
}
}
package com.company.annotation;
import java.lang.annotation.ElementType;
// 所有类型的 Class
public class test2 {
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);
// 只要元素类型与维度一样,就是同一个Class
int[] a = new int[10];
int[] b = new int[100];
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
}
}
Java 内存分析
类初始化
package com.company.annotation;
// 测试类声明时候会被初始化
public class test3 {
static {
System.out.println("Main 被加载");
}
public static void main(String[] args) throws ClassNotFoundException {
// 1. 主动引用
Son son = new Son();
// 2. 反射也会产生主动引用
Class.forName("com.company.annotation.Son");
// 不会产生类的引用方法
System.out.println(Son.b);
Son[] array = new Son[100];
}
}
class Father{
static int b = 2;
static {
System.out.println("父类被加载");
}
}
class Son extends Father{
static {
System.out.println("子类被加载");
m = 300;
}
static int m = 100;
static final int M = 1;
}
获得运行时类的完整结构
package com.company.annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
// 获取类的信息
public class test4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.company.annotation.User");
// 获得类的名字
System.out.println(c1.getName()); // 获得包名 + 类名
System.out.println(c1.getSimpleName());
// 获得类的属性
System.out.println("------------");
Field[] fields = c1.getFields(); // 只能找到public属性
fields = c1.getDeclaredFields(); // 找到全部的属性
for (Field field : fields){
System.out.println(field);
}
// 获得指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);
// 获得类的方法
System.out.println("------------");
Method[] methods = c1.getMethods();// 获得本类及其父类的全部public方法
for (Method method : methods){
System.out.println("正常的:" + method);
}
methods = c1.getDeclaredMethods(); // 获得本类的全部方法
for (Method method : methods){
System.out.println("getDeclaredMethods:" + method);
}
// 获得指定方法
// 重载
Method getName = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
// 获得指定的构造器
System.out.println("--------------");
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors){
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors();
for (Constructor constructor : constructors){
System.out.println(constructor);
}
// 获得指定的构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println("指定的:" + declaredConstructor);
}
}
有了Class对象后续操作
package com.company.annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class test5 {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException, ClassNotFoundException {
// 获得class对象
Class c1 = Class.forName("com.company.annotation.User");
// 构造一个对象
User user = (User)c1.newInstance(); // 本质是调用了类的无参构造器
System.out.println(user);
// 通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User)constructor.newInstance("快乐哥", 001, 20);
System.out.println(user2);
// 通过反射调用普通方法
User user3 = (User)c1.newInstance();
// 通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
// (对象, “方法的值”)
setName.invoke(user3, "olao");
System.out.println(user3.getName());
// 通过反射操作属性
System.out.println("---------------------");
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,我们需要关闭程序的安全监测,
// 开启访问权限
name.setAccessible(true);
name.set(user4, "oila");
System.out.println(user4.getName());
}
}
反射操作泛型
通过反射操作注解 (练习ORM)
package com.company.annotation;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class orm {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.company.annotation.Stu");
// 通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// 获得注解的value的值
TableStu tableStu = (TableStu)c1.getAnnotation(TableStu.class);
String value = tableStu.value();
System.out.println(value);
// 获得类指定注解
Field f = c1.getDeclaredField("name");
FieldStu annotation = f.getAnnotation(FieldStu.class);
System.out.println(annotation.columnName());
System.out.println(annotation.length());
System.out.println(annotation.type());
}
}
@TableStu("db_stu")
class Stu{
@FieldStu(columnName = "db_id", type = "int", length = 10)
private int id;
@FieldStu(columnName = "db_age", type = "int", length = 10)
private int age;
@FieldStu(columnName = "db_name", type = "varchar", length = 3)
private String name;
public Stu() {
}
public Stu(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Stu{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
// 类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableStu{
String value();
}
// 属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldStu{
String columnName();
String type();
int length();
}