一、注解
1.作用:不是程序本身,可以对程序作出解释;可以被其他程序读取。
2.格式:以"@注释名"在代码中存在,还可以添加一些参数值,如@SuppressWarnings(value=“unchecked”)
3.可以附加在package,class,method,field等上面,可以通过反射机制编程实现对这些元数据的访问。
二、元注解
元注解负责注解其他注解,JAVA定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明。
//Target 表示我们的注解可以用在哪些地方:方法上、类上等
@Target(value = {ElementType.METHOD,ElementType.TYPE})
//Retention 表示我们的注解在什么地方还有效果
//runtime>class>sources 运行时、生成class文件后、源码
@Retention(value = RetentionPolicy.RUNTIME)
//Documented 表示是否将我们的注解生成在JAVAdoc中
@Documented
//Inherited 子类可以继承父类的注解
@Inherited
@interface MyAnnotation{
}
三、注解的定义
注解的参数:参数类型+参数名();
若只有一个参数,名为value则可在括号内直接写参数。
public class Test {
@MyAnnotation(age = 18,name = "lxy")
public void test1(){}
}
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation{
String name();
int age();
int id() default -1; //有默认值
String[] schools() default {"qinghua"};
}
四、反射
加载完类之后,在堆内存的方法中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包括了完整的类的结构信息。Class类是Java反射的源头
反射方式:实例化对象–>getClass()方法–>得到完整的“包类名称”
获取class类的实例
1.若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高。
Class c1 = Person.class;
2.已知某个类的实例,调用该实例的getClass()方法获取Class对象
Class c2 = person.getClass();
3.已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出一个ClassNotFoundException
Class c3 = Class.forName(“demo01.Student”);
4.内置基本数据类型可以直接用类名.Type
5.还可以用ClassLoader
五、类加载
1.字节码.class文件加载到内存,所有类都会产生一个对应的class对象。
2.链接,将所有的静态变量初始化为0。
3.初始化:类初始化(new)时()方法执行静态代码,静态变量赋值。
六、获取类的运行时结构
package com.ayu.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test08 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class aClass = Class.forName("com.ayu.reflection.User");
System.out.println(aClass.getName()); //com.ayu.reflection.User
System.out.println(aClass.getSimpleName());//User
//获取类变量:只能获得public的
Field[] fields = aClass.getFields();
for (Field field:fields){
System.out.println(field);
}
//获取类变量:能获得所有的
fields = aClass.getDeclaredFields();
for (Field field:fields){
System.out.println(field);
}
//获取特定变量
System.out.println(aClass.getDeclaredField("name"));
//获取类方法:public
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取类方法:all
methods = aClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取特定方法
Method getName = aClass.getMethod("getName",null);
Method setName = aClass.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
}
//获取构造器
Constructor[] constructors = aClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
constructors = aClass.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println(declaredConstructor);
}
六、动态创建对象执行方法
创建类的对象:调用Class对象的newInstance()方法
- 类必须有一个无参构造器
- 类的构造器的访问权限要足够
没有无参构造器时,只需要在操作的时候明确调用类中的构造器,并将参数传递进去后,才可以实例化操作。
1)通过Class类的 getDeclaredConstructor(class…parameterTypes)取得本类的指定形参类型的构造器。
2)向构造器的形参中传递一个对象数组进去,里面包含了构造器所需的各个参数。
3)通过Constructor实例化对象
Class c1 = Class.forName("oop.demo02.Student");
// 本质是调用类的无参构造,如果没有无参构造,则需要先获取构造器
Student student = (Student) c1.newInstance();
System.out.println(student);
//获取构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class);
//使用构造器创建对象
Student s2 = (Student) declaredConstructor.newInstance("ayu",18);
System.out.println(s2);
Student s3 = (Student) c1.newInstance();
//获取方法,通过反射调用方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke 为s3调用setName方法,并传值
setName.invoke(s3,"lxy");
System.out.println(s3.getName());
//通过反射操作属性
Field declaredField = c1.getDeclaredField("age");
declaredField.setAccessible(true); //设置为true即可操作私有属性
declaredField.set(s3,19);
System.out.println(s3);
setAccessible:Method和Field、Constructor对象都有setAccessible()方法,其作用为启动和禁用访问安全检查的开关。true为取消检查,使得原本无法访问的私有成员也可以访问。
七、获取注解信息
package com.kuang.reflection;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.kuang.reflection.Student2");
Annotation[] annotation = c1.getAnnotations();
for (Annotation annotation1 : annotation) {
System.out.println(annotation1);
}//@com.kuang.reflection.Tableayu(value=db_table)
//获得注解的value值,要强制转换才能获取到.value()
Tableayu annotation1 = (Tableayu)c1.getAnnotation(Tableayu.class);
System.out.println(annotation1.value());//db_table
//获得指定属性的注解值
Field name = c1.getDeclaredField("name");
Fieldayu annotation2 = name.getAnnotation(Fieldayu.class);
System.out.println(annotation2.column());//db_name
}
}
@Tableayu("db_table")
class Student2{
@Fieldayu(column = "db_name",type = "varchar",length = 10)
String name;
@Fieldayu(column = "db_id",type = "int",length = 10)
int id;
@Fieldayu(column = "db_age",type = "int",length = 10)
int age;
public Student2() {
}
public Student2(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tableayu{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldayu{
String column();
String type();
int length();
}