java的注解与反射
最近跟着b站的狂神学习了反射和注解 来写篇博客巩固一下。
什么是注解
注解和注释挺像的,但是注释是给我们程序员看的,注解就是可以给程序员也可以给程序看的。所以注解的作用还是很大的
内置的几个注解:
@Override 重写一个方法
@Deprecated 不鼓励程序员使用,但是可以使用,或者存在更好的方式。
@SuppressWarnings 抑制编译警告
元注解
元注解就是负责注解其他注解的注解
元注解有下面那么几个
- @Target:用于描述注解的使用范围(该注解可以放在哪里)
- @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
- @Document:说明该注解将被包含在javadoc中
- @Inherited :说明子类可以继承父类中的该注解;
Target
参数:
Target使用的时候需要这样写,确定注解的使用范围
- TYPE : 类、接口或enum声明
- FIELD: 域(属性)声明
- METHOD: 方法声明
- PARAMETER: 参数声明
- CONSTRUCTOR: 构造方法声明 LOCAL_VARIABLE:局部变量声明
- ANNOTATION_TYPE:注释类型声明
- PACKAGE: 包声明
@Target({Element.METHDO,ElementType.Type})
/**
*value 可以忽略不写 只有一个参数的话
*/
Retention
最常用的使用方式
@Retention(value=RetentPolicy.RUNTIME);
自定义注解
常用格式:
@Target({Element.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnotation{
//注解的参数 : 参数类型+ 参数名();
String name() default "";
//推荐如果只有一个参数的话就取参数名为 value 这样在传入参数的时候可以省略写 value=XXX
}
反射
反射是框架中用到的很多的的有了反射,就让java变成了一个准动态的语言。
要了解反射就要知道的东西:
- Class 对象
- 一个类被加载后,类的整个结构都被封装在Class对象中
- Class本身自己也是一个类
- 通过Class可以完整的得到一个类中的所有被加载的结构
- Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象
获取Class对象的方法
-
通过对象获得
-
forname获取
-
通过类名.class获得
-
.基本内置类型的包装类的Type属性
-
获取获得父类的类型
使用方法 getSuperclass()
那些类型可以有Class对象
class: 外部类,成员(成员内部类、静态内部类),局部内部类 ,佚名内部类
interface: 接 口
[] :数组
enum:枚举
annotation:注解
primitive type:基本数据类型
void
用反射来创建一个对象
- 先获取一个Class类
Class c1=Class.forName("com.kuang.reflection.User"); //通过包名获取User类的Class 对象
- 构造一个对象
因为创建的对象返回的是Object我们这里知道是User对象所以可以直接强转,User user=(User)c1.newInstance();//本质是调用了类的无参构造器 //通过这种方式创建的对象和new的差不多。
这样创建的话需要User内必须要有无参构造器。 - 或者通过构造器创建对象
这个方法是获取类的构造器获取构造器都需要传入参数,这样我们就知道是需要那个构造器。我们这里就获取到 String,int,int 为参数的构造器。Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int class);
通过这样的方法创建的对象就是通过有参构造器构造的对象。User user =(User)constructor.newInstance("小陈",100,18);
通过反射调用方法
- 先获取方法
通过getDeclardMethod()方法我们可以获取一个Class下面的一个对象的方法。Method setName = c1.getDeclardMethod("setName",String.class);
–我们需要传入方法名字和参数类型 - 激活方法
利用激活方法我们可以给 指定的User对象,执行操作。setName.invoke(user,"狂神");
但是需要注意的是,这里需要留意 方法是不是public 类型的 - 利用反射操作属性
当属性是private 的时候,就需要通过setAccessible()来关闭安全检查Field name=c1.getDeclaredField("name"); name.setAccessible(true);//注意这里true是关闭安全检查 name.set(user,"狂狂");
当参数为true时,关闭安全检查
当参数为false时,开启安全检查,当然这里的关闭只是关闭当前的。
当关闭安全检查后可以提高反射执行的效率
反射读取注解
Class c1=Class.forName("com.kuang.reflection.User");
Anonotation[] annotations=c1.getAnnotations();//获取全部注解