写在前面
你们好,我是小庄。很高兴能和你们一起学习Java注解与反射的使用及原理。如果您对Java感兴趣的话可关注我的动态.
写博文是一种习惯,在这过程中能够梳理知识和巩固知识点。
前言
注解与反射在Java框架中广泛应用,极其重要,为了更好的掌握框架的知识,需要加深对注解和反射的了解
一、注解是什么?
可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。
二、注解有什么?
1.内置注解
内置注解 | 作用 |
---|---|
@Override | 标明一个方法打算重写超类(java.lang.*)中的另一个方法,子类重写父类的方法 |
@Deprecated | 可用于修饰类或属性,这个注解已经过时,不推荐使用 |
@SuppressWarnings(已定义好的参数) | 抑制编译时的警告信息 |
2.元注解
元注解 | 作用 |
---|---|
@Target() | 标识注解使用的范围,内部有设定好的枚举变量,如:TYPE(类),FIELD(属性),METHOD(方法) |
@Retention() | 注解的保存级别,SOURCE<CLASS<RUNTIME ,一般使用RUNTIME:表示运行时 |
@Documented | 该注解将被包含在javadoc中 |
@Inherited | 子类可以继承父类中的Inherited注解 |
三、注解的使用
代码如下(示例):
package com;
import java.lang.annotation.*;
import java.util.Arrays;
//设置作用域
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
//设置保存级别
@Retention(RetentionPolicy.RUNTIME)
//设置注解保存在javadoc中
@Documented
//子类可以继承父类中的Inherited注解
@Inherited
//@interface 注解名 ,@interface使用后会调用java.lang.Annotation类
@interface Test1{
/**
*name()在这里是属性,不是方法!default是设置默认参数值
*如果设置的是String name();则使用注解时必须要加参数
*/
String name() default "";
}
/**
*@Inherited进行特别讲解
*/
@Test1(name = "小庄")
class Parent{
}
//子类没有写注解,但是继承了父类
class Sun extends Parent{
}
public class Test{
public static void main(String[] args){
//将子类用一个变量操作
Class c = Sun.class;
/**
* c.getAnnotation(Test1.class)-->获取注解Test1
* 打印使用的注解
*/
System.out.println((c.getAnnotation(Test1.class)));
}
}
效果图
四、反射是什么
正常方式:
反射方式:
小结: 反射与正常的方式相反,可以逆推出该对象所在的包,并且能获取属性、方法、构造器等等
1、获得反射对象
一个类在内存中只有一个Class对象
//Class.forName(类所在的路径。例:包.文件夹.类的名称)
Class c = Class.forName("com.User");
System.out.println(c);
2、通过反射操作对象
1、创建一个User实体类
public class User{
private String name;
public User(){}
public User(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2、反射操作对象代码
package com;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test2 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//com是我的包名,User是com包下类名
Class c = Class.forName("com.User");
//默认使用无参构造方法进行类加载
User u1 = (User) c.newInstance();
//打印结果为User{name='null'}
System.out.println(u1);
//以下使用有参构造方法
//获取一个构造器
Constructor constructor = c.getDeclaredConstructor(String.class);
//给user设置类加载,并带参数
Use u2 = (User) constructor.newInstance("小庄");
//打印结果为User{name='小庄'}
System.out.println(u2);
/**
*通过反射操作类的方法
*/
//获取User类的setName方法
Method setName = c.getMethod("setName", String.class);
//invoke:激活。激活对象u2的方法setName,参数为"小庄2"
setName.invoke(u2,"小庄2");
//打印结果为:小庄2
System.out.println(u.getName());
/**
*通过反射操作属性
*/
//通过反射获取User的name属性
Field name = c.getDeclaredField("name");
//赋予安全权限
name.setAccessible(true);
//设置属性的值,u2为User对象,”小庄3为参数“
name.set(u2,"小庄3");
//打印结果为:小庄3
System.out.println(u3.getName());
}
}
五、注解和反射的配合使用
代码如下:
package com;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class ReflectonAndAnnotation{
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException {
//通过反射获取对象
Class c = Class.forName("com.User");
//获取对象的所有注解
Annotation[] annotations = c.getAnnotations();
//遍历打印该对象的所有注解
for (Annotation annotation:annotations){
System.out.println(annotation);
}
//获取指定对象的注解
Table table =(Table) c.getAnnotation(Table.class);
//获取该注解中的属性name的值
String name = table.name();
//打印注解中的属性name的值
System.out.println(name);
//通过对象进行反射获取指定属性:username
Field username = c.getDeclaredField("username");
//通过指定属性获得指定的注解内容
FileName annotation = username.getAnnotation(FileName.class);
//打印内容
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
//类名的注解
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String name() ;
}
//属性的注解
@Target(ElementType.FIELD)//属性域
@Retention(RetentionPolicy.RUNTIME)
@interface FileName{
String columnName();
String type();
int length() default 10;
}
@Table(name = "db_user")
class User{
@FileName(columnName = "db_name",type = "varchar",length = 30)
private String username;
@FileName(columnName = "db_age",type = "int",length = 3)
private Integer age;
public User(){}
public User(String username, Integer age) {
this.username = username;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
public void setUsername(String username) {
this.username = username;
}
public void setAge(Integer age) {
this.age = age;
}
public String getUsername() {
return username;
}
public Integer getAge() {
return age;
}
}
总结
路漫漫其修远兮,吾将上下而求索。
Java的学习需要一步一个脚印,打好基础才能仰望远方。
喜欢我的话,可以关注!我将与你一起努力