反射
用来在程序的运行期间可以反射提供的一些API来获取某个类的内部结构信息,并基于或得到的信息完成对象的创建和访问操作
用来进行框架底层设计的,开发中很少直接使用
框架(通用性)=反射+注解+设计模式
反射相关的类都是定义在java.lang.reflect包中
反射从一定程度上来说破坏了类的封装性
反射获取对象
- 调用Class类的静态方法forName(String ClassName) 来获取某个类的字节码对象(用的最多)
- 通过类名.class的方式也可以获取到一个类的字节码对象
- 对象名.getClass() 来获取字节码对象
注意:一个类的字节码对象在类加载的时候创建,每个类的字节码对象在内存中只有一份
反射创建对象
newInstance()默认调用的是类的无参构造器进行对象的实例化,也可以调用类中的有参构造进行对象的实例化
Constructor constructor = c1.getConstructor(String.class,String.class,int.class);
Object instance2 = constructor.newInstance(“zhangsan”,“male”,19);
通过反射修改属性值与调用方法
代码举例
package com.qianfeng.day21;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
try {
//获得字节码对象
Class clazz = Class.forName("com.qianfeng.day21.Student");
//根据字节码对象获得Object对象
Object stu = clazz.newInstance();
// System.out.println(stu);
//设置对象某个属性的值
Field filed1 = clazz.getDeclaredField("name");
//将private改为可见
filed1.setAccessible(true);
//通过反射的方法改变属性的值
filed1.set(stu,"zhangsan");
System.out.println(((Student)stu).getName());
//通过反射的方式完成对一个对象方法的调用
Method method = clazz.getMethod("hello");
method.invoke(stu);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
注解
注解也称为Annotation 用来对我们的代码部件进行描述的一般在后期的应用中主要用来进行配置
注解不影响我们代码的执行
注解分为几种情况:有些注解只能在编译期间发挥作用,就是给编译器看的用于编译的语法检查
比如:
@override重写
@Deprecated调用时会出现删除线,表示已经过时
@SuppressWarnings(“unchecked”)告诉编译器忽略 unchecked 警告信息,
还有一些注解使用来在运行期发挥作用的,可以使用反射的方式在程序的执行期间读取某个类或方法上的注解信息进行使用
JDK中提供了很多的注解供开发人员使用,有时我们需要自己根据需求定义新的注解
自定义注解:
public @interface 注解的名称 {
可以在注解中定义属性来保存信息
}
如果注解中没有属性的定义,该注解从作用来说其实就相当于是一个标记
@Target(ElementType.METHOD)//元注解:用来标记注解的注解
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
注解的使用方式:@注解名称
元注解:@Retention(RetentionPolicy.SOURCE) 使用定义注解作用范围
RetentionPolicy.SOURCE:表示当前注解编译器发生作用
我们自定义的注解都是属于runtime类型,运行期发挥作用
注解所携带的信息在运行期间是通过反射的技术进行获取的