一、注解
1.1、什么是注解?
- 注解是java 1.5开始引入的
- 格式:@注解名 可以添加参数
- 注解可以用在包,类,方法,参数等上面,可以通过反射机制实现对这些元注解的访问
1.2、元注解
- @Target: 用于描述注解的适用范围
- @Retention: 用于描述直接的生命周期(RUNTIME>CLASS>SOURCE)
- @Documented: 表示该注解将被作用在javadoc中
- @Inherited: 说明子类可以继承父类的该注解
1.3、自定义注解
#定义
@Target(value = {ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Chen {
String name = "";
String value = "";
}
#使用
public class Test1 {
@Chen
private void test(){
}
}
二、反射
2.1、什么是反射?
java是静态语言,但是反射允许在程序运行期间 借助于Reflection api获取类的内部信息,并能直接操作任意类的内部属性及方法.
- 优点 可以动态创建对象和编译
- 缺点 对性能有影响
2.2、反射的使用
1、获取反射对象
Class c1= Class.forName("com.chen.learn01.learn4.Student");
Class c2=new Student().getClass();
Class c3=Student.class;
Class c4=Integer.TYPE;
2、获取类加载器
//获取系统里的加载器
ClassLoader classLoader=ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//获取系统类加载器发父类加载器---》扩展类加载器
ClassLoader parent=classLoader.getParent();
System.out.println(parent);
//获取扩展类加载器的父类加载器---》跟加载器
ClassLoader c=parent.getParent();
System.out.println(c);
3、获取类运行时结构
//获取包名+类名
System.out.println(c1.getName());
//获取类名
System.out.println(c1.getSimpleName());
System.out.println("-------------------------------------------");
//获取public属性
Arrays.stream(c1.getFields()).forEach(c-> System.out.println(c.getName()));
System.out.println("-------------------------------------------");
//获取本类所有属性
Arrays.stream(c1.getDeclaredFields()).forEach(c-> System.out.println(c.getName()));
System.out.println("-------------------------------------------");
//获取指定的属性名
System.out.println(c1.getDeclaredField("name"));
System.out.println("-------------------------------------------");
//获取指定的public属性名 没有会报错
// System.out.println(c1.getField("name"));
System.out.println("-------------------------------------------");
//获取本类及父类所有public的方法
Arrays.stream(c1.getMethods()).forEach(c-> System.out.println(c.getName()));
System.out.println("-------------------------------------------");
//获取本类所有的方法
Arrays.stream(c1.getDeclaredMethods()).forEach(c-> System.out.println(c.getName()));
System.out.println("-------------------------------------------");
Method method1=c1.getMethod("setName",String.class);
Method method2=c1.getMethod("getName",null);
method2.invoke(c1,null);
4、通过反射动态创建对象
//获取Class对象
Class c1= Class.forName("com.chen.learn01.learn4.Student");
//本质是调用无参构造器
Student s=(Student) c1.newInstance();
System.out.println(s);
//通过构造器创建对象
Constructor constructor= c1.getConstructor(String.class,int.class,int.class);
Student s1=(Student)constructor.newInstance("chen",1,1);
System.out.println(s1);
//通过反射调用普通方法
Student s2=(Student) c1.newInstance();
Method method=c1.getMethod("setName",String.class);
method.invoke(s2,"chen111");
System.out.println(s2.getName());
Field field=c1.getDeclaredField("name");
//修改私有属性时 需要开启
field.setAccessible(true);
field.set(s2,"chen222");
System.out.println(s2.getName());