学习:菜鸟教程

注解(Annotation)

内置的注解

Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。

  • @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
  • @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
  • @SuppressWarnings - 指示编译器去忽略注解中声明的警告。

元注解

**作用在其他注解的注解 **

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
  • @Documented - 标记这些注解是否包含在用户文档中。
  • @Target - 标记这个注解应该是哪种 Java 成员。
  • @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

自定义注解(@interface)

使用 @interface 自定义注解时﹐自动继承了java.lang.annotation.Annotation接口

  • interface用来声明一个注解﹐格式:public @interface注解名{定义内容}
  • 其中的每一个方法实际上是声明了一个配置参数.
  • 方法的名称就是参数的名称.
  • 返回值类型就是参数的类型(返回值只能是基本类型,Class , String , enum )
  • 可以通过default来声明参数的默认值
  • 如果只有一个参数成员,一般参数名为value
  • 注解元素必须要有值﹐我们定义注解元素时,经常使用空字符串,0作为默认值.

展示:

1
2
3
4
5
6
7
8
9
10
@Documented
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyAnno1{
//注解的参数:参数类型 + 参数名();
String name() default "瞳瞳";
int id() default -1; //默认值为-1,代表不存在
String[] schools() default {"B站大学","哈哈大学"};
}

反射

获取Class的三方式

方式备注
Class.forName(“完整类名带包名”)静态方法
对象.getClass()
任何类型.class

通过反射实例化对象

newInstance()方法内部实际上调用了无参数构造方法,必须保证无参构造存在才可以。

c1.newInstance();

Class类方法

方法名备注
T newInstance()创建对象
String getName()返回完整类名带包名
String getSimpleName()返回类名
Field[] getDeclaredFields()返回类中所有的属性
Field getDeclaredField(String name)根据属性名name获取指定的属性

Field类方法

void set(Object obj, Object value)设置属性值
Object get(Object obj)读取属性值

set()不可以直接访问私有属性,需要打破封装,才可以

1
field1.setAccessible(true);     //默认false,设置为true为打破封装,set()可以访问私有属性
1
2
3
4
5
6
7
8
Class c1 = Class.forName("reflection.Person");
Object obj = c1.newInstance();
System.out.println(obj); //Person{name='null', sex='null'}

Field f1 = c1.getDeclaredField("name");
f1.setAccessible(true); //默认false,设置为true为打破封装,set()可以访问私有属性
f1.set(obj,"xm"); //属性赋值
System.out.println(obj); //Person{name='xm', sex='null'}

注解与反射

获取类注解实例

1
c1.getAnnotations()

获取属性注解实例

1
2
3
4
//获取属性
Field f1 = c1.getDeclaredField("name");
//获取属性注解实例(多)
Annotation[] a2 = f1.getAnnotations();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Person person=new Person();
Class c1 = person.getClass();
//属性上
//获取类注解实例(单)
Annotation a1 = c1.getAnnotation(AnnoTable.class); //这个是AnnoTable自定义注解
System.out.println(a1); //@reflection.AnnoTable("hello")

//获取属性
Field f1 = c1.getDeclaredField("name");
//获取属性注解实例(多)
Annotation[] a2 = f1.getAnnotations();
for (Annotation annotation : a2) {
System.out.println(annotation); //@reflection.AnnoFile(id=1, value="xingming")
}


//方法上
Method m1 = c1.getDeclaredMethod("setSex", String.class);

for (Annotation annotation : m1.getAnnotations()) {
System.out.println(annotation);
}

利用注解与反射自定义一个Frame

注解

1
2
3
4
5
6
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
String value() default "";
}

测试

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
public class A_R {

@MyTest
public void test1() {
System.out.println("-----------test1----------------");
}

//@MyTest
public void test2() {
System.out.println("-----------test2----------------");
}

@MyTest
public void test3() {
System.out.println("-----------test3----------------");
}

@MyTest(value = "hello")
public void test4() throws Exception {
System.out.println("-----------test4----------------");
//得到Class对象
Class a = A_R.class;
//提取该成员方法
Method m = a.getDeclaredMethod("test4");
//得到注解实例
MyTest t1 = m.getAnnotation(MyTest.class);
System.out.println(t1.value()); //hello

}


public static void main(String[] args) throws Exception{
A_R a=new A_R();
//1、得到Class对象
Class c=A_R.class;
//2、提取这个类中的全部成员方法
Method[] m = c.getDeclaredMethods();
//3.
for (Method method : m) {
if (method.isAnnotationPresent(MyTest.class)){
//说明当前方法上是存在@MyTest,触发当前方法执行。
method.invoke(a);
}
}
}
}