注解
注解的作用:
不是程序本身,可以对程序做出解释,和注释有相似之处。
可以被其他程序(如编译器)所读取。
注解的格式:以“@注解名”在代码上存在,还可以在其中添加一些参数。
注解在哪里使用:可以附在包,类,方法,字段上面。等于给他们添加了额外的辅助信息。我们可以通过反射机制实现对这些元数据的访问。
注解举例:
@override:重写的注解
@Deprecated:过时的注解
元注解:对注解的注解。有如下四类元注解。
@Target:用于描述注解的使用范围(即被描述的注解可以用在什么地方)
@Retention:表示需要在什么级别保存注释信息,用于描述注解的生命周期(source>class>runtime)
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
自定义注解:使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
声明注解
@interface用来声明一个注解,格式:public @interface 注解名{定义内容} ,其中的每一个方法实际是声明了一个配置参数,方法的名称就是参数的名称,返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum),可以通过default来声明参数的默认值,如果只有一个参数成员,一般参数为value,注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值。
反射
反射概念
JVM为每个加载的class创建了一个Class实例,包含了类的各种信息包括类名,包名,方法,字段,父类,实现的接口,因此我们只要得到了Class实例就可以获取类的相关信息。这种通过Class实例获得class相关信息的方法称为反射。
反射的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和方法
- 在运行时处理注解
- 生成动态代理
获取Class实例的方法
注意class在jvm中创建的Class实例是唯一的。
1. Class cls = string.classs
2. String hello = "hello"
Class cls = hello.getClass()
3. Class cls = Class.forName("java.lang.String")
反射访问字段
//四种方法获取字段
Field getField(name)//根据字段名获取某个pubic的field(包括父类)
Field getDeclaredField(name)//根据字段名获取当前类的field。
Field [] getField()//获取所有public的field(包括父类)
Field [] getDeclareField()//获取当前类的所有field(不包括父类)
实例
package com.south.reflection;
import java.lang.reflect.Field;
public class GetName {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class cls = Class.forName("com.south.reflection.student");
Field field = cls.getField("name");
System.out.println(field);
Field field1 = cls.getField("score");
//Field field2 = cls.getDeclaredField("grade");
System.out.println(field1);
//System.out.println(field2);
}
}
class person{
public String name;
}
class student extends person{
public int score;
private int grade;
字段值
注意:在调用get前需写一句
f.setAccessible(true)
这是无论该字段是不是public,一律允许访问。
Object p = new Person("Xiao Ming");
Class c = p.getClass();
Field f = c.getDeclaredField("name");
//获得字段值
Object value = f.get(p);
System.out.println(value); // "Xiao Ming"
//设置字段值
f.set(p,"xiaohong")
获得方法
- 通过Class实例的方法可以获取Method实例:getMethod(),getMethods(),getDeclaredMethod(),getDeclaredMethods();
- 通过Method实例可以获取方法信息:getName(),getReturnType(),getParameterTypes(),getModifiers()其中
参数为方法名和参数的Class实例。 - 通过Method实例可以调用某个对象的方法:Object invoke(Object instance, Object… parameters)第一个为调用哪个对象的方法,后面的参数为调用方法的参数。
- 通过设置setAccessible(true)来访问非public方法;
实例
package com.south.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class GetName {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
student student = new student();
Class cls = Class.forName("com.south.reflection.student");
Method method = cls.getMethod("getName");
method.setAccessible(true);
String str = (String) method.invoke(student);
System.out.println(str);
}
}
class person{
public String name;
public String getName(){
return name;
}
}
class student extends person{
public int score;
private int grade;
public int getScore(){
return score;
}
public int grade(){
return grade;
}
}
调用构造方法
我们通常通过new创建新的实例,如果用反射机制即获得Class实例后调用newInstance()方法即可创建新的实例。这样创建必须在类中有无参构造函数。如果想通过有参构造函数创建新的实例该如何作?
package com.south.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class GetName {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
Class cls = Class.forName("com.south.reflection.student");
Constructor constructor = cls.getConstructor(int.class);
student student1 = (student) constructor.newInstance(123);
System.out.println(student1.score);
}
}
class person{
public String name;
public String getName(){
return name;
}
}
class student extends person{
public int score;
private int grade;
public int getScore(){
return score;
}
public int grade(){
return grade;
}
public student(int n){
this.score=n;
}
}