java注解与反射
一、元注解
//元注解
@Target({ElementType.METHOD,ElementType.TYPE})//注解用在哪儿:方法 或 类
@Retention(RetentionPolicy.RUNTIME)//何时有效:runtime>class>sources
@Documented//将注解生成在javadoc中
@Inherited//子类可以继承父类的注解
@Deprecated//废弃的
@SuppressWarnings("all")//镇压警告
@interface MyAnnotation{
String[] name();//成员变量要加()
int age() default 18;//default表示默认值
}
@MyAnnotation(name={"张三","张德旺"},age=33)
public class TestAnnotation extends Object{
@MyAnnotation(name={"张三","张德旺"},age=33)
public static void main(String[] args) {
System.out.println();
}
}
二、反射
获得反射的class
package day27__Annotation;
public class TestReflection {
public static void main(String[] args) throws ClassNotFoundException {
TestAnnotation ta = new TestAnnotation();
//System.out.println(ta);
Class<? extends TestAnnotation> c1 = ta.getClass();
System.out.println(c1);
Class<?> c2 = Class.forName("day27__Annotation.TestAnnotation");
System.out.println(c2);
Class c3 = TestAnnotation.class;
System.out.println(c3);
//内置基本类型,都会有一个type
Class it = Integer.TYPE;
System.out.println(it);
Class<?> c5 = c1.getSuperclass();
System.out.println(c5);
}
}
练习:获取以下类型的class
class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
interface:接口
[]∶数组
enum:枚举
annotation:注解@interface
primitive type:基本数据类型
void
public class TestReflection2 {
public static void main(String[] args) {
System.out.println("类:"+Student.class);//类
System.out.println("数组:"+int[].class);//数组
System.out.println("二维数组:"+int[][].class);//二维数组
System.out.println("接口:"+List.class);//接口
System.out.println("枚举:"+ElementType.class);//枚举
System.out.println("int:"+int.class);
System.out.println("Integer:"+Integer.class);
System.out.println("void:"+void.class);
System.out.println("Class:"+Class.class);
}
}
1.获取成员变量:
练习:对 Student 类,通过反射得到其中的字段,并练习使用 set 和 get 方法
package day27_Reflection;
public class Student {
public String name;
protected int age;
String gender;
private int id;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
if (id != student.id) return false;
if (name != null ? !name.equals(student.name) : student.name != null) return false;
return gender != null ? gender.equals(student.gender) : student.gender == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
result = 31 * result + (gender != null ? gender.hashCode() : 0);
result = 31 * result + id;
return result;
}
public Student() {
}
public Student(String name, int age, String gender, int id) {
this.name = name;
this.age = age;
this.gender = gender;
this.id = id;
}
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;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", id=" + id +
'}';
}
}
package day27_Reflection;
public class Student {
public String name;
protected int age;
String gender;
private int id;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
if (id != student.id) return false;
if (name != null ? !name.equals(student.name) : student.name != null) return false;
return gender != null ? gender.equals(student.gender) : student.gender == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
result = 31 * result + (gender != null ? gender.hashCode() : 0);
result = 31 * result + id;
return result;
}
public Student() {
}
public Student(String name, int age, String gender, int id) {
this.name = name;
this.age = age;
this.gender = gender;
this.id = id;
}
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;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", id=" + id +
'}';
}
}
2. 获取构造器
两种 get 方式的区别:
Class类的getConstructor()方法,无法获取到类的私有构造器.
Class类的getDeclaredConstructor()方法,可获取到类的私有构造器(包括带有其他修饰符的构造器),但必须设置setAccessible(true)
练习:通过反射获取Class的构造器,并分别创建有参和无参的实例。
package day27_Reflection;
public class TestReflectionConstructor {
public static void main(String[] args) throws Exception {
Constructor studentConstructor=Student.class.getConstructor(String.class,int.class,String.class,int.class);
System.out.println(studentConstructor);
Student zs=studentConstructor.newInstance("张三",23,"男",12121212);
System.out.println(zs);
Student stu1 = Student.class.newInstance();//newInstance 继承自class类
Student stu2 = Student.class.getConstructor().newInstance();
System.out.println(stu1);
System.out.println(stu2);
}
}
3 获取方法
练习:利用反射获取方法
public class TestReflectionMethod {
public static void main(String[] args) throws Exception {
Method eatMethod = Student.class.getMethod("eat");
Method eatMethod2= Student.class.getMethod("eat",String.class);
Student stu=Student.class.newInstance();
eatMethod.invoke(stu);
eatMethod2.invoke(stu,"noodle");
System.out.println(eatMethod.getname());
}
}
练习:反射案例
需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法
解题思路:
1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中
2.在程序中加载读取配置文件
3.使用反射技术来加载类文件进内存
4.创建对象
5.执行方法 method.invoke(Object)
学生类:
public class Student {
String name;
int id;
void eat(){
System.out.println("eat...");
}
void eat(String food){
System.out.println("eat "+food);
}
}
教师类:
public class Teacher {
void sleep(){
System.out.println("sleep...");
}
}
反射测试类:
public class TestReflection {
public static void main(String[] args) throws Exception {
//1. 创建一个空properties,并加载
Properties pro = new Properties();
InputStream is=TestReflection.class.getResourceAsStream("pro.properties");
pro.load(is);
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
Class<?> aClass = Class.forName(className);
Object obj= aClass.newInstance();
Method method=aClass.getDeclaredMethod(methodName);
//激发invoke
method.invoke(obj);
}
}
配置文件 pro.properties(与 Student 同一文件夹)
className=day28.Teacher methodName=sleep
修改配置文件
className=day28.Student methodName=eat
输出会发生变化