注解和反射_1
p1-p9
1: 注解
1.1 注解的概念
注解:能给人看,也能给机器看 ,机器会用反射机制进行访问。
如@Override都是注解,注解具有检查和约束的作用.如把S小写,override就报错了。
1.2 内置注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package annotation; import java.util.ArrayList; import java.util.List; /** * author liulei * data 5.21 * since 1.8 * version 1.0 * Description 内置注解演示 */ public class Demo01 { //Override 重写的注释 @Override public String toString(){ return super.toString(); } //Deprecated 不推荐程序员使用,但是可以使用,或者存在更好的方式 @Deprecated public static void test() { System. out .println( "这是个不被推荐的方法" ); } @SuppressWarnings( "all" ) public void test02() { List list = new ArrayList(); } public static void main(String[] args) { test(); } } |
1.3 元注解
自定义的注解的类型都是@interface +名字的类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | package annotation; import java.lang.annotation.*; /** * author liulei * data 5.21 * since 1.8 * version 1.0 * Description 元注解演示 */ @Myannotation public class Demo02 { @Myannotation public void test() { } @Myannotation2(age = 18,name = "liulei" ) public void test1(){ }<br> //注解如果参数没有默认值,我们必须显示赋值 @Myannotation3(value = "ll" ) public void test2(){ } } //定义一个注解 //Target 表示注解可以用在哪些地方 //Retention 表示我们的注解在什么地方还有效,作用的范围 //runtime>class>source //Documented 表示是否将注解生成在Javadoc中 //Inherited 子类可以继承父类的注解 @Target(value = {ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @ interface Myannotation{ } @ interface Myannotation2{ //注解的参数:参数类型+参数名(); String name() default "" ; int age(); int id() default -1; //如果默认为-1,代表不存在 String[] schools() default { "西部开源" , "清华大学" }; } @ interface Myannotation3{ String value(); //如果只有一个参数,则参数为value } |
常用的四个注解就是下面四个,其中Retention表示注解的生命周期,绝大部分情况我们声明的注解都是运行时期间有效(RUNTIME),尤其是自带的注解,所以我们自定义的一定要加上
1 | Target 表示注解可以用在哪些地方,如ElementType.TYPE则表示这个注解只能用在类上, |
2:反射
2.1 反射介绍
2.2 Class类
1 package Reflection; 2 3 /** 4 * author liulei 5 * data 5.21 6 * since 1.8 7 * version 1.0 8 * Description 获取类对象的Class对象的几种方法 9 */ 10 public class Test01 { 11 public static void main(String[] args) throws ClassNotFoundException { 12 Person p = new Student("abc"); 13 System.out.println("这个人是:"+p.name); 14 //方式一:通过对象获得 15 Class c1 = p.getClass(); 16 System.out.println(c1.hashCode()); 17 //方式二:forname获得 18 Class c2 = Class.forName("Reflection.Student"); 19 System.out.println(c2.hashCode()); 20 //方式三:通过类名.class获得 21 Class c3 = Student.class; 22 System.out.println(c3.hashCode()); 23 //方式四:基本内置类型都有一个Type属性 24 Class c4 = Integer.TYPE; 25 System.out.println(c4); 26 //获得父类类型 27 Class c5 = c1.getSuperclass(); 28 System.out.println(c5); 29 } 30 31 } 32 class Person{ 33 public String name; 34 35 public Person(String name) { 36 this.name = name; 37 } 38 public Person() { 39 } 40 41 } 42 class Student extends Person 43 { 44 public Student(String name) { 45 this.name = name; 46 } 47 } 48 class Teacher extends Person 49 { 50 public Teacher() { 51 } 52 53 public Teacher(String name) { 54 this.name = "老师"; 55 } 56 }
1 package Reflection; 2 3 import java.lang.annotation.ElementType; 4 5 /** 6 * author liulei 7 * data 8 * since 1.8 9 * version 1.0 10 * Description 11 */ 12 public class Test02 { 13 public static void main(String[] args) { 14 Class c1 = Object.class;//类 15 Class c2 = Comparable.class;//接口 16 Class c3 = String[].class;//数组 17 Class c4 = int[][].class;//二维数组 18 Class c5 = Override.class;//注解 19 Class c6 = ElementType.class;//枚举 20 Class c7 = Integer.class;//基本数据类型 21 Class c8 = void.class;//void 22 Class c9 = Class.class;//Class 23 System.out.println(c1); 24 System.out.println(c2); 25 System.out.println(c3); 26 System.out.println(c4); 27 System.out.println(c5); 28 System.out.println(c6); 29 System.out.println(c7); 30 System.out.println(c8); 31 System.out.println(c9); 32 33 //只要元素类型与维度一致,就是同一个Class 34 int[] a = new int[10]; 35 int[] b =new int[100]; 36 System.out.println(a.getClass().hashCode()); 37 System.out.println(b.getClass().hashCode()); 38 39 } 40 }
2.3 类的加载
先把class文件加载到内存,静态数据转换为运行时数据,获取对应的java.lang.Class,链接阶段,为类变量分配内存空间,并赋值默认初始值,初始化阶段则是调用cinit方法合并静态变量和静态代码块并赋值初始值。父类没初始化也要初始化父类,cinit方法保证了枷锁和同步。
1 package Reflection; 2 3 /** 4 * author liulei 5 * data 6 * since 1.8 7 * version 1.0 8 * Description 9 */ 10 public class Test03 { 11 public static void main(String[] args) { 12 A a = new A(); 13 System.out.println(A.m); 14 } 15 } 16 /* 17 1 加载到内存,会产生一个类对应的Class对象 18 2 链接,链接结束后 m = 0 19 3 初始化 20 <clinit>() 21 { 22 System.out.println("A类静态代码块初始化"); 23 m = 300; 24 m = 100; 25 } 26 */ 27 class A{ 28 static { 29 System.out.println("A类静态代码块初始化"); 30 m = 300; 31 } 32 static int m = 100; 33 34 public A() { 35 System.out.println("A类的无参构造初始化"); 36 } 37 }
通过数组定义类引用,只是创建了一些空间,空间的名字叫son而已。常量在链接的解析阶段就加载到类对象里面,已经完成赋值,不属于类初始化。
过程
作者:你的雷哥
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!