目录
JAVA自带的注解--10个(4个注解在java.lang.annotation,6个注解在java.lang)
通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等
注解(Annotation)
是JDK5.0开始引入的一种注释机制
以@注解名的形式存在于代码中,Java中内置了一些注解,比如:@Override。当然也可以自定义注解。注解也可以有参数,例如@MyAnnotation(value = "菠萝吹雪")。
Annotation可以用在什么地方呢?
类、接口、方法、变量、参数以及包等之上。
注解可以设置存在于不同的生命周期中,例如SOURCE(源码中),CLASS(Class文件中,默认是此保留级别),RUNTIME(运行期中)。
举例:下面我们重写一个toString方法。
@Override
public String toString() {
return super.toString();
}
然后我们CTRL+左键,进入到Override的源码中,如图可以看到Override的注解,可以看到,是从jdk1.5开始的。
注解的作用
1.作为一种辅助信息,对程序做出一些解释。
例如:@Override注解作用域方法上,表示此方法是重写了父类的方法。
2.可以被其他程序读取。例如:编辑器。
注解中也可以有方法
1.定义方法的格式:String name();
2.可以有默认值,也可以没有,如果没有默认值,在使用的时候必须填写对应的值,如果需要有默认值,使用default指定默认值。
3.如果想在使用的时候不指定具体名字,方法名写value
在Java整个注解体系中,有三个非常重要的主干类
Annotation接口
Annotation可以为哪些程序元素设置元数据呢?
Annotation提供了为元素设置元数据的方法:包括修饰包、类、构造器、方法、成员变量、参数、局部变量的声明。
元数据的信息被存储在Annotation的"name=value"中。
ElementType 枚举
用来指定注解的类型,意思是:我的注解要用在哪里?
RetentionPolicy 枚举
用来指定注解的策略,不同类型的策略指定的注解的作用域不同。
(1)SOURCE,注解仅存在于编译器处理期间,编译器处理完之后,这个注解就没用了
(2)CLASS,注解在class文件中依然有效
(3)RUNTTME,编译器是不起作用的,只有在运行期由JVM读取。
JAVA自带的注解--10个(4个注解在java.lang.annotation,6个注解在java.lang)
作用在代码上的注解
@Override:注解仅作用在方法上,被标识方法表示重写父类的方法,用这个注解可以避免方法名跟参数写错。
@Deprecated:意思是说此方法已过时,过时的原因就是有新的API的类替代了次方法。被划去的方法仍然是可以正常使用的,就是一个提示而已。
@SuppressWarnings:编辑器去忽略警告
public class Ch01 { @Deprecated @SuppressWarnings("all") public void info() { }
@SafeVarargs :Java 7开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
@FunctionalInterface:Java 8 开始支持,标识一个匿名函数或函数式接口。
@Repeatable:Java 8 开始支持,标识某注解可以在同一个声明上使用多次。
元注解
专门给注解加的注解。可以理解为:元注解也是标签,但它是一种特殊的标签,作用和目的就是给其他普通标签进行解释说明。
基本的元标签有
@Documented:标记这个注解是否包含在用户文档中
@Target:这个注解可以修饰哪些信息
@Inherited(继承):如果一个类用上了@Inherited注解,那么其子类也会继承这个注解
@Retention:标识这个注解的作用域
反射
Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。
下面我们定义一个类----Person
package com.ys.reflex;
public class Person {
//私有属性
private String name = "Tom";
//公有属性
public int age = 18;
//构造方法
public Person() {
}
//私有方法
private void say(){
System.out.println("private say()...");
}
//公有方法
public void work(){
System.out.println("public work()...");
}
}
得到class的三种方式
//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object
// 类型的对象,而我不知道你具体是什么类,用这种方法
Person p1 = new Person();
Class c1 = p1.getClass();
//2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
// 这说明任何一个类都有一个隐含的静态成员变量 class
Class c2 = Person.class;
//3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
// 但可能抛出 ClassNotFoundException 异常
Class c3 = Class.forName("com.ys.reflex.Person");
通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等
getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
getMethod(String name, Class[ ] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
演示
//获得类完整的名字
String className = c2.getName();
System.out.println(className);//输出com.ys.reflex.Person
//获得类的public类型的属性。
Field[] fields = c2.getFields();
for(Field field : fields){
System.out.println(field.getName());//age
}
//获得类的所有属性。包括私有的
Field [] allFields = c2.getDeclaredFields();
for(Field field : allFields){
System.out.println(field.getName());//name age
}
//获得类的public类型的方法。这里包括 Object 类的一些方法
Method [] methods = c2.getMethods();
for(Method method : methods){
System.out.println(method.getName());//work waid equls toString hashCode等
}
//获得类的所有方法。
Method [] allMethods = c2.getDeclaredMethods();
for(Method method : allMethods){
System.out.println(method.getName());//work say
}
//获得指定的属性
Field f1 = c2.getField("age");
System.out.println(f1);
//获得指定的私有属性
Field f2 = c2.getDeclaredField("name");
//启用和禁用访问安全检查的开关,值为 true,则表示反射的对象在使用时应该取消 java 语言的访问检查;反之不取消
f2.setAccessible(true);
System.out.println(f2);
//创建这个类的一个对象
Object p2 = c2.newInstance();
//将 p2 对象的 f2 属性赋值为 Bob,f2 属性即为 私有属性 name
f2.set(p2,"Bob");
//使用反射机制可以打破封装性,导致了java对象的属性不安全。
System.out.println(f2.get(p2)); //Bob
//获取构造方法
Constructor [] constructors = c2.getConstructors();
for(Constructor constructor : constructors){
System.out.println(constructor.toString());//public com.ys.reflex.Person()
}