反射
反射允许对成员变量,成员方法和构造方法的信息进行编程访问
利用反射获取class对象的三种方式
1 Class.forName("全类名") 全类名:包名+类名 copy reference
2 类名.class
3 对象.getClass( )
源代码阶段 从.java到.class阶段 用1 //最为常用的
在内存中加载阶段 用2 //一般更多的是当作参数传递
在内存中运行阶段 new一个新对象 用3 //当我们有了这个类的对象时,才可以使用
获取class对象代码实现:
public class MyReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
//第一种
Class clazz = Class.forName("MyReflect.Student");
System.out.println(clazz);
//第二种
Class<Student> clazz2 = Student.class;
System.out.println(clazz2);
//第三种
Student s = new Student();
Class<? extends Student> clazz3 = s.getClass();
System.out.println(clazz3);
System.out.println(clazz==clazz2);
System.out.println(clazz2==clazz3);
}
}
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
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 "MyReflect.Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
利用反射获取构造方法
通过class对象获取构造方法代码实现:

注意括号里面的写法!!!
打印结果:
利用反射获取成员变量
1 获取class字节码文件的对象
Class clazz = Class.forName("myReflect2.Student");
2 获取所有的成员变量
Field[] fields = clazz.getDeclaredFields();
3 获取单个的成员变量
Field name = clazz.getDeclaredField("name");
4 进而获取成员变量记录的值

5 修改对象里面记录的值

打印结果:
利用反射获取成员方法
1 获取字节码文件对象
2 获取里面所有公共的方法对象(包括父类中所有的公共方法)

3 获取里面所有的方法对象(不能获取父类的,但是可以获取本类中私有的方法)

4 获取指定的单一方法
()里面不仅要写方法名字,还要写参数类型

5 获取方法抛出的异常

6 方法运行
方法代码:

方法运行代码:

反射的作用
1 获取一个类里面的所有信息,获取到了之后,再执行其他的业务逻辑
2 结合配置文件,动态的创建对象并调用方法

反射练习题
1 保存信息
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
public class ReflectDemo {
public static void main(String[] args) throws IllegalAccessException, IOException {
Student s = new Student("小妮子",18);
Teacher t = new Teacher("Yang",35);
saveObject(s);
}
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
//获取字节码文件的对象
Class<?> clazz = obj.getClass();
//创建IO流
BufferedWriter bw = new BufferedWriter(new FileWriter("myreflect\\a.txt"));
//获取所有的成员变量
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
//获取成员变量的名字
String name = field.getName();
//获取obj对象中 成员变量的值
Object value = field.get(obj);
bw.write(name+"="+value);
bw.newLine(); //写一行换一行
}
bw.close();
}
}
Teacher类中有 name salary 构造方法 toString
Student类中有name age 构造方法 toString
2 与配置文件结合,动态的创建对象,并调用方法
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//读取配置文件中的信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("myreflect\\prop.properties");
prop.load(fis);
fis.close();
System.out.println(prop);
//获取全类名和方法名
String className = (String) prop.get("classname");
String methodName = (String) prop.get("method");
System.out.println(className);
System.out.println(methodName);
//利用反射创建对象并运行方法
Class<?> clazz = Class.forName(className);
//获取构造方法
Constructor<?> con = clazz.getDeclaredConstructor();
Object o = con.newInstance(); //创建对象
System.out.println(o);
//获取成员方法并运行
Method method = clazz.getDeclaredMethod(methodName);
method.setAccessible(true);
method.invoke(o);
}
}
Student类、Teacher类在上一题的基础上分别加了一个学习,教书方法
注解
作用
本身不是代码的一部分,不会影响代码的执行
在编译、类加载和运行时被读取和处理
为开发者提供了一种以非侵入性的方式为代码提供额外信息的手段
基本语法
注解是使用 @interface 关键字定义的,并且默认继承自 Annotation 接口。
public @interface MyAnnotation {
String value() default "";
int count();
}
注意括号里面的写法!!!

