注解和反射
注解【Annotation】
已有的注解
@Override/@SuppressWarnings
元注解
- 常见有两个,用来自定义注解
@Target
表示注解要用在什么地方
@Retention
表示注解在什么时候有效,源码/编译,一般自定义的注解都用Runtime
自定义注解
//类上的注解
@Annotation2("成功") //因为此注解只有一个参数,可以不写value=
public class Annotation {
//方法上的注解
@MyAnnotation(n = -1, x = 'a') //不能直接写-1,'a'必须加上 n=,x=
public void function() {
}
}
//自定义注解1
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
//参数类型,参数名,可以有默认值
String name() default "yes"; //如果有default,注解就可以不给参数,否则一定要参数
int n();
char x();
}
//自定义注解2
@Target({ElementType.METHOD,ElementType.TYPE}) //TYPE表示作用域在类上
@Retention(RetentionPolicy.RUNTIME)
@interface Annotation2 {
String value(); //如果注解只有一个参数,可以定义成value(),注解实现的时候就不用写value=...
}
反射【Reflection重点】
- 反射是干嘛的?
在运行的过程中可以获取类的任意属性,太太太猛了!直接让JAVA可以称为一门动态语言
怎么获得Class对象
- 几乎所有的类型都有Class对象
public class MyClass {
public static void main(String[] args) throws Exception {
Person person = new Student("学生");
//获取Class对象方法1
Class c1=person.getClass();
System.out.println(c1.hashCode());
//方法2
Class c2 = Class.forName("com.xu.day12.Student");
System.out.println(c2.hashCode());
//方法3
Class c3 = Student.class;
System.out.println(c3.hashCode());
//通过Class对象可以获取类的很多属性
System.out.println(c1.getSuperclass());
System.out.println(c1.getName());
System.out.println(c1.toString());
}
}
class Person {
String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person {
public Student(String name) {
super(name);
}
}
class Teacher extends Person {
public Teacher(String name) {
super(name);
}
}
//输出
356573597
356573597
356573597
class com.xu.day12.Person
com.xu.day12.Student
class com.xu.day12.Student
通过反射动态创建一个类的对象,调用其构造方法、普通方法、修改其属性
- 通过反射获得对象类型是
Object
,方法类型是Method
,属性类型是Field
public class MyClass {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.xu.day12.Person");
//用反射动态创建对象方法一
Person p1 = (Person) c1.newInstance(); //此方法是通过调用类的无参构造来实现的
//一旦类没有无参构造的时候,方法一就不可行了
//创建对象方法二
Constructor cons=c1.getConstructor(char.class, String.class, int.class); //注意此处的写法
Person p2=(Person) cons.newInstance('男',"小明",100);
System.out.println(p2.toString());
//通过反射获取类的方法
java.lang.reflect.Method method=c1.getDeclaredMethod("setName", String.class);//注意此处的参数,需要先输入name再输入类型
method.invoke(p1,"小王"); //此处调用方法需要先传入对象才行
System.out.println(p1.getName());
//通过反射修改类的属性
Person p3=(Person)c1.newInstance();
Field field=c1.getField("age");
field.setAccessible(true); //这是安全检查的开关,注意,如果不加这句话,私有属性不可修改
field.set(p3, 888);
System.out.println(p3.getAge());
}
}
class Person {
public char sex;
private String name;
private int age;
public Person() {
System.out.println("无参构造被调用了");
}
public Person(char sex, String name, int age) {
this.sex = sex;
this.name = name;
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"sex=" + sex +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
通过反射操作泛型
了解即可
通过反射操作注解【重点】
public class GetAnnotationByReflection {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
//获取类的注解
Class c = Class.forName("com.xu.day12.Student");
TableName annotation = (TableName) c.getAnnotation(TableName.class);//重点:这句话的意思是获取TableName类型的注解
System.out.println(annotation.value());
//获取属性的注解
Field field=c.getField("id"); //需要先获取属性
TableField annotation2=field.getAnnotation(TableField.class); //传入参数是此属性的注解类型TableField
System.out.println(annotation2.clumnName());
System.out.println(annotation2.type());
System.out.println(annotation2.lenth());
}
}
@TableName("db_Student")
class Student {
@TableField(clumnName = "db_id",type = "int",lenth = 10)
private int id;
@TableField(clumnName = "db_age",type = "int",lenth = 10)
private int age;
@TableField(clumnName = "db_name",type = "String",lenth = 10)
private String name;
public Student() {
}
public Student(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
}
@Target(ElementType.TYPE) //作用域是类
@Retention(RetentionPolicy.RUNTIME)
@interface TableName {
String value();
}
@Target(ElementType.FIELD) //作用域是类
@Retention(RetentionPolicy.RUNTIME)
@interface TableField {
String clumnName();
String type();
int lenth();
}