注解Annotation
内置注解
- @Override
- @Deprecated
- @SuppressWarnings
| public class Test1 { |
| |
| |
| @Override |
| public String toString(){ |
| return super.toString(); |
| } |
| |
| |
| @SuppressWarnings("all") |
| public void test2(){ |
| List list = new ArrayList<>(); |
| } |
| |
| |
| @Deprecated |
| public void test(){ |
| |
| } |
| } |
元注解:注解其他的注解
-
@Target
ElementType.TYPE
:允许被修饰的注解作用在类、接口和枚举上
ElementType.FIELD
:允许作用在属性字段上
ElementType.METHOD
:允许作用在方法上
ElementType.PARAMETER
:允许作用在方法参数上
ElementType.CONSTRUCTOR
:允许作用在构造器上
ElementType.LOCAL_VARIABLE
:允许作用在本地局部变量上
ElementType.ANNOTATION_TYPE
:允许作用在注解上
ElementType.PACKAGE
:允许作用在包上
-
@Retention
RetentionPolicy.SOURCE
:当前注解编译期可见,不会写入 class 文件
RetentionPolicy.CLASS
:类加载阶段丢弃,会写入 class 文件
RetentionPolicy.RUNTIME
:永久保存,可以反射获取
-
@Document
-
@Inherited
| |
| @Target(value = ElementType.METHOD) |
| @Retention(value = RetentionPolicy.RUNTIME) |
| @Documented |
| @Inherited |
| @interface MyAnnotation { |
| } |
| import java.lang.annotation.ElementType; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.annotation.Target; |
| |
| class Test { |
| |
| @MyAnnotation2(name = "haha") |
| public void test() { |
| } |
| |
| @MyAnnotation3("注解只有一个时,用value或者省略value=,直接写内容") |
| public void test2() { |
| } |
| } |
| |
| |
| @Target({ElementType.TYPE, ElementType.METHOD}) |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface MyAnnotation2 { |
| |
| String name(); |
| |
| int age() default 0; |
| |
| int id() default -1; |
| |
| String[] schools() default {"a", "b"}; |
| } |
| |
| @interface MyAnnotation3 { |
| |
| String value(); |
| } |
反射Reflection
- 动态创建对象和编译,但对性能有影响(解释型操作)
- Class本身也是一个类
- Class对象只能由系统建立对象
- 一个加载的类在jvm中只会有一个Class实例
- 一个Class对象对应的是一个加载到jvm中的一个.class文件
- 每个类的实例都会记得自己是由哪个Class实例所生成
- 通过CLass可以完整的得到一个类中的所有被加载的结构
- Class类是Reflection的根源,想动态加载,必须先获得Class对象
| class Test { |
| |
| public static void main(String[] args) throws ClassNotFoundException { |
| Class<?> c1 = Class.forName("User"); |
| Class<?> c2 = Class.forName("User"); |
| |
| |
| |
| System.out.println(c1.hashCode()); |
| System.out.println(c2.hashCode()); |
| } |
| } |
| |
| 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 Test2 { |
| public static void main(String[] args) throws ClassNotFoundException { |
| Person person = new Student(); |
| |
| |
| Class<? extends Person> c1 = person.getClass(); |
| System.out.println(c1); |
| System.out.println(c1.hashCode()); |
| |
| |
| Class<?> c2 = Class.forName("Student"); |
| System.out.println(c2); |
| System.out.println(c2.hashCode()); |
| |
| |
| Class<Student> c3 = Student.class; |
| System.out.println(c3); |
| System.out.println(c3.hashCode()); |
| |
| |
| Class<Integer> c4 = Integer.TYPE; |
| System.out.println(c4); |
| |
| |
| Class<?> c5 = c1.getSuperclass(); |
| System.out.println(c5); |
| } |
| } |
| |
| class Person { |
| public 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 = "student"; |
| } |
| } |
| |
| class Teacher extends Person { |
| public Teacher() { |
| this.name = "teacher"; |
| } |
| } |
所有类型的Class
| import java.lang.annotation.ElementType; |
| |
| class Test { |
| public static void main(String[] args) { |
| Class<Object> c1 = Object.class; |
| Class<Comparable> c2 = Comparable.class; |
| Class<String[]> c3 = String[].class; |
| Class<int[][]> c4 = int[][].class; |
| Class<Override> c5 = Override.class; |
| Class<ElementType> c6 = ElementType.class; |
| Class<Integer> c7 = Integer.class; |
| Class<Void> c8 = void.class; |
| Class<Class> c9 = Class.class; |
| |
| |
| int[] a = new int[10]; |
| int[] b = new int[1000]; |
| System.out.println(a.getClass().hashCode()); |
| System.out.println(b.getClass().hashCode()); |
| } |
| } |
类加载内存分析
- 类的加载过程
- 加载:将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由类加载器完成
- 链接:将类的二进制数据合并到JRE中,正式为类变量(static)分配内存并设置类变量默认初始值
- 初始化:jvm负责对类进行初始化<clinit>
| package Reflection; |
| |
| public class Test4 { |
| public static void main(String[] args) { |
| A a = new A(); |
| System.out.println(A.m); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
| } |
| |
| class A{ |
| static { |
| System.out.println("A类静态代码块"); |
| m = 300; |
| } |
| |
| static int m = 100; |
| |
| public A(){ |
| System.out.println("A类的无参构造"); |
| } |
| } |
- 何时发生类初始化
- 主动引用(发生初始化)
- jvm启动时,先初始化main所在的类
- new一个类的对象
- 调用类的静态成员(除了final常量)和静态方法
- 使用java.lang.reflect包的方法对类进行反射调用
- 初始化一个类,如果他的父类没有初始化,会先初始化父类
- 被动引用(不发生)
- 访问一个静态域时,只有真正声明这个域的类才会被初始化,如通过子类引用父类的静态变量,不会导致子类初始化
- 通过数组定义类引用,不会触发此类的初始化
- 引用常量不会触发(常量在链接阶段就存入调用类的常量池中了)
| package Reflection; |
| |
| public class Test5 { |
| static { |
| System.out.println("Main类加载"); |
| } |
| |
| public static void main(String[] args) throws ClassNotFoundException { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| System.out.println(Son.M); |
| |
| } |
| } |
| |
| class Father{ |
| static int b = 2; |
| static { |
| System.out.println("father加载"); |
| } |
| } |
| |
| class Son extends Father{ |
| static { |
| System.out.println("son加载"); |
| m = 300; |
| } |
| |
| static int m = 100; |
| static final int M = 1; |
| } |
| package Reflection; |
| |
| public class Test6 { |
| public static void main(String[] args) throws ClassNotFoundException { |
| |
| ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); |
| System.out.println(systemClassLoader); |
| |
| |
| ClassLoader parent = systemClassLoader.getParent(); |
| System.out.println(parent); |
| |
| |
| ClassLoader parent1 = parent.getParent(); |
| System.out.println(parent1); |
| |
| |
| ClassLoader classLoader = Class.forName("Reflection.Test6").getClassLoader(); |
| System.out.println(classLoader); |
| |
| |
| classLoader = Class.forName("java.lang.Object").getClassLoader(); |
| System.out.println(classLoader); |
| |
| |
| System.out.println(System.getProperty("java.class.path")); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
| } |
获取运行时类的完整结构
| package Reflection; |
| |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.Method; |
| |
| public class Test7 { |
| public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { |
| Class<?> c1 = Class.forName("Reflection.User"); |
| |
| User user = new User(); |
| c1 = user.getClass(); |
| |
| |
| System.out.println(c1.getName()); |
| System.out.println(c1.getSimpleName()); |
| |
| |
| Field[] fields = c1.getDeclaredFields(); |
| for(Field field: fields){ |
| System.out.println(field); |
| } |
| |
| |
| Field name = c1.getDeclaredField("name"); |
| System.out.println(name); |
| |
| |
| Method[] methods = c1.getMethods(); |
| for(Method method:methods){ |
| System.out.println(method); |
| } |
| methods = c1.getDeclaredMethods(); |
| for(Method method:methods){ |
| System.out.println(method); |
| } |
| |
| |
| |
| Method getName = c1.getMethod("getName", null); |
| Method setName = c1.getMethod("setName", String.class); |
| System.out.println(getName); |
| System.out.println(setName); |
| |
| |
| 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); |
| |
| } |
| } |
动态创建对象执行方法
| package Reflection; |
| |
| import java.lang.reflect.Field; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| |
| public class Test8 { |
| public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { |
| Class c1 = Class.forName("Reflection.User"); |
| |
| |
| User user = (User)c1.getDeclaredConstructor().newInstance(); |
| System.out.println(user); |
| User user2 = (User)c1.getDeclaredConstructor(String.class,int.class,int.class).newInstance("haha", 1, 2); |
| System.out.println(user2); |
| |
| |
| User user3 = (User) c1.getDeclaredConstructor().newInstance(); |
| Method setName = c1.getDeclaredMethod("setName", String.class); |
| setName.invoke(user3, "xixi"); |
| System.out.println(user3.getName()); |
| |
| |
| User user4 = (User) c1.getDeclaredConstructor().newInstance(); |
| Field name = c1.getDeclaredField("name"); |
| |
| name.setAccessible(true); |
| name.set(user4, "hehe"); |
| System.out.println(user4.getName()); |
| |
| } |
| } |
| package Reflection; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| |
| public class Test9 { |
| |
| public static void test1(){ |
| User user = new User(); |
| long startTime = System.currentTimeMillis(); |
| |
| for (int i = 0; i < 10_0000_0000; i++) { |
| user.getName(); |
| } |
| |
| long endTime = System.currentTimeMillis(); |
| System.out.println((endTime - startTime) + "ms"); |
| } |
| |
| |
| public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { |
| User user = new User(); |
| Class c1 = user.getClass(); |
| Method getName = c1.getMethod("getName", null); |
| |
| long startTime = System.currentTimeMillis(); |
| |
| for (int i = 0; i < 10_0000_0000; i++) { |
| getName.invoke(user,null); |
| } |
| |
| long endTime = System.currentTimeMillis(); |
| System.out.println((endTime - startTime) + "ms"); |
| } |
| |
| |
| |
| public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { |
| User user = new User(); |
| Class c1 = user.getClass(); |
| Method getName = c1.getMethod("getName", null); |
| getName.setAccessible(true); |
| |
| long startTime = System.currentTimeMillis(); |
| |
| for (int i = 0; i < 10_0000_0000; i++) { |
| getName.invoke(user,null); |
| } |
| |
| long endTime = System.currentTimeMillis(); |
| System.out.println((endTime - startTime) + "ms"); |
| } |
| |
| public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { |
| test1(); |
| test2(); |
| test3(); |
| |
| |
| |
| |
| |
| } |
| } |
反射操作范型
| package Reflection; |
| |
| import java.lang.reflect.Method; |
| import java.lang.reflect.ParameterizedType; |
| import java.lang.reflect.Type; |
| import java.util.List; |
| import java.util.Map; |
| |
| public class Test10 { |
| public void test1(Map<String, User> map, List<User> list){ |
| System.out.println("test1"); |
| } |
| |
| public Map<String, User> test2(){ |
| System.out.println("test2"); |
| return null; |
| } |
| |
| public static void main(String[] args) throws NoSuchMethodException { |
| Method method = Test10.class.getMethod("test1", Map.class, List.class); |
| Type[] genericParameterTypes = method.getGenericParameterTypes(); |
| for(Type type:genericParameterTypes){ |
| System.out.println(type); |
| if(type instanceof ParameterizedType){ |
| Type[] actualTypeArguments = ((ParameterizedType)type).getActualTypeArguments(); |
| for (Type actualTypeArgument : actualTypeArguments) { |
| System.out.println(actualTypeArgument); |
| } |
| } |
| } |
| |
| |
| method = Test10.class.getMethod("test2", null); |
| Type genericReturnType = method.getGenericReturnType(); |
| if(genericReturnType instanceof ParameterizedType){ |
| Type[] actualTypeArguments = ((ParameterizedType)genericReturnType).getActualTypeArguments(); |
| for (Type actualTypeArgument : actualTypeArguments) { |
| System.out.println(actualTypeArgument); |
| } |
| } |
| } |
| } |
对象关系映射ORM
| package Reflection; |
| |
| import java.lang.annotation.*; |
| |
| public class Test11 { |
| public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { |
| Class c1 = Class.forName("Reflection.Student2"); |
| |
| |
| Annotation[] annotations = c1.getAnnotations(); |
| for (Annotation annotation : annotations) { |
| System.out.println(annotation); |
| } |
| |
| |
| Table annotation = (Table) c1.getAnnotation(Table.class); |
| String value = annotation.value(); |
| System.out.println(value); |
| |
| |
| java.lang.reflect.Field f = c1.getDeclaredField("name"); |
| Field annotation1 = f.getAnnotation(Field.class); |
| System.out.println(annotation1.columnName()); |
| System.out.println(annotation1.type()); |
| System.out.println(annotation1.length()); |
| } |
| } |
| |
| |
| @Table("db_student") |
| class Student2{ |
| @Field(columnName = "db_id", type = "int", length = 10) |
| private int id; |
| @Field(columnName = "db_age", type = "int", length = 10) |
| private int age; |
| @Field(columnName = "db_name", type = "varchar", length = 3) |
| private String name; |
| |
| public Student2(){ |
| |
| } |
| |
| public Student2(int id, int age, String name) { |
| this.id = id; |
| this.age = age; |
| this.name = name; |
| } |
| |
| @Override |
| public String toString() { |
| return "Student2{" + |
| "id=" + id + |
| ", age=" + age + |
| ", 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; |
| } |
| } |
| |
| |
| @Target(ElementType.TYPE) |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface Table{ |
| String value(); |
| } |
| |
| |
| @Target(ElementType.FIELD) |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface Field{ |
| String columnName(); |
| String type(); |
| int length(); |
| } |
例子
| import java.lang.annotation.ElementType; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.annotation.Target; |
| import java.lang.reflect.Field; |
| |
| class Tester { |
| public static void main(String[] args) throws IllegalAccessException { |
| |
| Student student = new Student(1L, "haha", "123456789012"); |
| System.out.println(validate(student)); |
| } |
| |
| public static String validate(Object o) throws IllegalAccessException { |
| |
| Field[] fields = o.getClass().getDeclaredFields(); |
| |
| for (Field field : fields) { |
| |
| if (field.isAnnotationPresent(Length.class)) { |
| |
| Length length = field.getAnnotation(Length.class); |
| field.setAccessible(true); |
| |
| int value = ((String) field.get(o)).length(); |
| |
| if (value < length.max() || value > length.max()) { |
| return length.errMsg(); |
| } |
| } |
| } |
| return null; |
| } |
| } |
| |
| @Target(ElementType.FIELD) |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface Length { |
| int min(); |
| |
| int max(); |
| |
| String errMsg(); |
| } |
| |
| class Student { |
| private Long id; |
| private String name; |
| @Length(min = 11, max = 11, errMsg = "手机号码必须11位") |
| private String mobile; |
| |
| public Student(Long id, String name, String mobile) { |
| this.id = id; |
| this.name = name; |
| this.mobile = mobile; |
| } |
| |
| public Student() { |
| } |
| |
| public Long getId() { |
| return id; |
| } |
| |
| public void setId(Long id) { |
| this.id = id; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public String getMobile() { |
| return mobile; |
| } |
| |
| public void setMobile(String mobile) { |
| this.mobile = mobile; |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步