这里注解和反射的学习仅仅是一点基础的梳理,仅限于为使用javaweb打基础,更深入的内容还是去实践或者查阅文档吧
1.java注解
用来修饰对象,方法类之类的东西
1.常见的注解
//junit注解 @Test @After @Before
//jdk自带三个注解 Override强制认为是重写 Deprecate表示这个被注解对象过期
//SupportWarning("")用来屏蔽编译器报错
2.自定义注解以及赋值
public @interface MyAnnotation {//看起来很很像是方法,但是这东西叫配置参数,需要在调用注解的时候进行赋值String[] value1();int value2();
}调用的时候是这样的
@MyAnnotation(value1 = {"第一个参数","而且这是个数组"},value2 = 1)
3.四大元注解
//这四个是元注解,要写在注解文件里面的,平时用不到
@Retention(RetentionPolicy.CLASS)//这东西放在注解文件里面,这个注解的控制生命周期
@Target(value = {TYPE,FIELD,METHOD})//指定这个注解能注解什么东西
@Documented //代表被注解的类会提取成文档
@Inherited //代表被继承的类如果使用了Inherited修饰的注解,子类也自动带有该注解
public @interface MyAnnotation {//看起来很很像是方法,但是这东西叫配置参数,需要在调用注解的时候进行赋值String[] value1();int value2();
}
2.Java反射
1.Java反射机制:
正常的类加载流程是通过new实例化一个对象,然后调取对象内部的方法。而反射机制就是和正常的反过来,我们直接根据一些方法得到Class类的对象,然后根据这个Class对象去获取这个类的一些信息(个人的粗浅理解)
2.神魔是class对象?
class类对象,并不是我们寻常定义的那些,这类对象不是我们能够定义的,而是类加载器生成的。通俗来讲,class类对象是修饰类的类(天知道这句话啥意思),本质上来说class类对应的是一个一个的class文件。
每当我们定义了一个类,编译器会将其编译为.class文件,里面包含了这个类的信息
同时jvm还会对应这个class文件生成一个class对象,这个class对象就像一个窗口,能对应访问class文件和里面的信息,这个过程也可以称之为反射
(内存分析以后再说)
3.获取class对象的方法如下
//Class对象对应的是JVM中的class文件,包含了一个类所有的信息//集中获取class的方法//1.第一种,通过类的名字获取Class<?> a1= Class.forName("Anno_refl.user");//(注意这里要的是类的属性)///2.第二种,直接用类的静态属性classClass<?> a2=user.class;//3.第三种,根据类的实例对象获取Class<?> a3=u.getClass();//4.第四种,根据基本数据类型用TYPE获取Class<?> a4= Integer.TYPE;//(这个也有class属性)//获取一个class对象后,我们就可以得到这类的全部信息,比如这个类的父类是什么Class<?> a_father=a1.getSuperclass();//例如这里直接获得了object类
其中2.3是来源于object,也就是说所有类都会继承这个方法,也就是通用的
4.获取到class类对象后,我们可以从中获取我们需要的信息:
这里注意一个问题,比如Method,Field这些类和class类很像,都是对应某个方法,某个属性,但是这些无法统筹在class类里面
//获取类的简单名字String SimpleName=a1.getSimpleName();//获取类的完整名字(包括包名字)String name=a1.getName();//获取类的指定属性(public)Field field=a1.getField("num");//获取类的指定属性(全部)Field field2=a1.getDeclaredField("num");//获取全部的public属性Field[] arrFields=a1.getFields();//获取全部的属性Field[] arrFields2=a1.getDeclaredFields();//获取指定的方法(需要指明方法名字和参数类型(参数类型也要class类))Method method=a1.getMethod("getNum");Method method2=a1.getMethod("setNum",Integer.TYPE);//获取全部的public方法Method[] arrMethod=a1.getMethods();//获取全部的方法Method[] arrMethod2=a1.getDeclaredMethods();
5.也可以反过来利用class类对象创建实例化的对象
主要有两个方法:第一个newIntance,这个默认调用无参构造器生成对象
第二个方法是先创建构造器类,再根据这个构造器类对象进行实例化
//利用反射创建对象user u1= (user) a1.newInstance();//这个方法有更好的替代,而且记得要强转一下Constructor<?> constructor=a1.getDeclaredConstructor(Integer.TYPE);//调用某个有参构造器user u2= (user) constructor.newInstance(12);
6.根据获取到的一些信息进行调用:
举例子:对get到的Method进行调用的方法为invoke(obj,para)
u为一个实例化的对象
method是u对应的class类里面获取到的Method类对象
12,是这个Method对象对应的方法所需要的参数
method.invoke(u,12)
获取属性和设置属性的方法分别为set,get
//在实例化对象u中获取,field对应的属性
field.get(u)
//在实例化对象u中获取,field对应的属性,并将其修改为12
field.set(u,12)
其他还有获取注解等方法,大同小异了