1. 正文
1. 注解
2. 反射
2. 注解
1. 注释: 对代码加以解释。注释给程序员看。
2. 注解: 注解给程序看。
注解得种类。
1. 预定义注解。 系统中自动得一些注解。
2. 自定义注解。
3. 元注解。
2.1 预定义注解。---JVM虚拟机来解析。
1. @Override: 重写得注解。符合重写得规则。
2. @Deprecated: 表示已过时。
3. @SuppressWarnings: 表示压制警告。
4. @FunctionInterface: 表示函数式接口。表示该接口中有且仅有一个抽象方法。
2.2 自定义注解---初级。
格式:
public @interface 注解名{
//注解得属性。
}
使用自定义注解:
@注解名(属性名=属性值)
public class Test03 {
}
//自定义注解
@interface MyAnnotation{
}
//使用自定义得注解
@MyAnnotation //譬如 @RequestMapping
class Student{
@MyAnnotation
private String name;
@MyAnnotation
public void show(){
}
}
注意: 我们在定义好注解后,并使用了该注解,但是并没有对我们得程序产生影响。要想让自定义得注解有效,必须解析注解【反射时来解析。】。
疑惑: @Override 因为JVM解析了该注解。 @Controller 因为Spring框架解析了该注解。
2.3 元注解。
元注解就是声明在注解上得注解。
1. @Target(value=可以取下面这些内容): 作用限制注解使用得位置。
/** 表示可以作用在类,接口,枚举 */ TYPE,
/** 属性 */ FIELD,
/** 普通方法上 */ METHOD,
/** 方法参数 */ PARAMETER,
/** 构造方法上 */ CONSTRUCTOR,
/** 局部变量 */ LOCAL_VARIABLE2.
@Retention: 注解什么时候生效。默认时源码 java经历了那些阶段。
源码阶段-->字节码阶段--->运行阶段
/** * 源码时生效 */ SOURCE,
/** * 字节码时生效 */ CLASS,
/** * 运行时生效。 * 在JVM内存中还有该注解。 */ RUNTIME
3. @Documented 当生产API文档时该注解还存在。
4. @Inherited 是否运行被子类继承。
2.4 自定义注解---高级
我们刚才定义得注解中什么属性都没写。正常得注解可能会存在一些属性。如何定义注解中得属性。
public @interface 注解名{
数据类型 属性名() default 默认值;
}
数据类型:基本数据类型 字符串 枚举 数组[只能是上面类型得数组] 注解
注解本身没有任何意义。只有通过解析该注解才能使其富有真正得意义。通过反射来解析得注解。
3. 反射---框架设计得灵魂。--ORM
框架:它是一种半成品。好处: 提高开发得效率。
反射: 类在运行时把类中得成员[方法,属性,构造方法,注解]抽取为其他类得过程叫做反射
任何一个类在JVM中都存在一个影子反射对象。
3.1 如何获取反射类---Class类。
这里提供了三种获取Class类对象的方式
1. Class.forName("类的全路径");
场景: 比如 加载驱动时。 和<bean id="" class="全路径"/>
spring框架根据全类获取该类的反射类。
2. 类名.class
场景: 在mybatis BookDao bookDao = session.getMapper(BookDao.class);
3. 对象名.getClass();
在指定对象名的情况下使用这种方式。
public class Test01 {
public static void main(String[] args) throws Exception{
//①Class.forName()
Class<?> aClass = Class.forName("com.ykq.demo01.Student");
//②类名.class
Class<Student> aClass1 = Student.class;
//③对象名.getClass();
Student s=new Student();
Class<?> aClass2 = s.getClass();
//思考这三个对象的地址是否相同。 任何一个字节码在JVM中有且仅存在一个对象。(相同)
System.out.println(aClass==aClass1);
System.out.println(aClass==aClass2);
}
}
class Student{
public String name;
public void show(){
System.out.println("show方法");
}
}
3.2 通过反射类获取对象的类对象。
//1.通过反射类获取对应的类对象。
Class<Student> aClass = Student.class;
Student student = aClass.newInstance();
System.out.println(student);
3.3 获取属性类对象--Field.
Field getDeclaredField(String name) 获取本类中指定名称的Field对象
Field[] getDeclaredFields() 获取本类中所有的Field对象。
Field getField(String name) 获取本类以及父类中public修饰的指定Field对象。
Field[] getFields() 获取本类以及父类中public修饰的所有属性。
public class Test01 {
public static void main(String[] args) throws Exception{
Class<Student> aClass = Student.class;
Student student = aClass.newInstance();//通过反射获取对应的实例对象
System.out.println(student);
System.out.println("=================获取本类中指定的属性对象===================");
Field name = aClass.getDeclaredField("name");
name.set(student,"某某某"); //为指定属性赋值
Field age = aClass.getDeclaredField("age");
age.set(student,22);
Field width = aClass.getDeclaredField("width");
width.setAccessible(true); //设置允许访问私有的成员
width.set(student,20.0);
System.out.println(student);
System.out.println("=================获取本类中所有的属性对象===================");
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField :declaredFields){
System.out.println(declaredField);
}
System.out.println("=================获取本类以及父类中所有的public属性对象===================");
Field[] fields = aClass.getFields();
for (Field field:fields){
System.out.println(field);
}
}
public static void 通过反射类获取实例对象()throws Exception{
//1.通过反射类获取对应的类对象。
Class<Student> aClass = Student.class;
Student student = aClass.newInstance();
System.out.println(student);
}
public static void 获取反射类对象()throws Exception{
//①Class.forName()
Class<?> aClass = Class.forName("com.ykq.demo01.Student");
//②类名.class
Class<Student> aClass1 = Student.class;
//③对象名.getClass();
Student s=new Student();
Class<?> aClass2 = s.getClass();
//思考这三个对象的地址是否相同。 任何一个字节码在JVM中有且仅存在一个对象。
System.out.println(aClass==aClass1);
System.out.println(aClass==aClass2);
}
}
class People{
public Double height;
}
class Student extends People{
public String name;
public Integer age;
private Double width;
public void show(){
System.out.println("show方法");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", width=" + width +
'}';
}
}
3.3.1 Field类中常见的方法。
1. set(Object o,Object value);为指定对象的属性赋值。
2. setAccessible(true);设置允许操作私有属性。
3.4 获取方法类对象--Method
Method getMethod(String name, Class<?>... parameterTypes)
获取本类以及父类种指定方法名的public方法。
Method[] getMethods() :获取本类以及父类种所有的public方法。
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
获取本类种指定方法名的方法
Method getDeclaredMethods()
获取本类中所有方法
public class Test02 {
public static void main(String[] args) throws Exception{
Class<Doctor> aClass = Doctor.class;
System.out.println("~~~~~~~~~~~~~~~~~~~获取本类以及父类种指定名称的public方法");
Method fun = aClass.getMethod("fun");
System.out.println(fun);
Method fun2 = aClass.getMethod("fun2",String.class,Integer.class);
System.out.println(fun2);
System.out.println("~~~~~~~~~~~~~~~~~~~获取本类以及父类种所有的public方法");
Method[] methods = aClass.getMethods();
for (Method m:methods){
System.out.println(m);
}
System.out.println("~~~~~~~~~~~~~~~~获取本类种指定方法名的方法");
Method fun3 = aClass.getDeclaredMethod("fun3", String.class);
System.out.println(fun3);
}
}
class Doctor{
public String name;
public void fun(){
System.out.println("hello fun");
}
public void fun2(String name){
System.out.println("hello fun2==="+name);
}
private void fun3(String name){
System.out.println("hello fun2==="+name);
}
public void fun2(String name,Integer age){
System.out.println("hello fun2==="+name+"==="+age);
}
}
3.4.1 Method类种常见的方法
Object r=invoke(Object,Object...value):回调指定方法。
setAccessible(true);设置允许操作私有属性。
4. 获取注解类对象---Annotation.
Annotation getAnnotation(String name, Class<?>... parameterTypes)
获取本类以及父类中注解。
Annotation[] getAnnotations() :获取本类以及父类种所有注解。
Annotation getDeclaredgetAnnotation(String name, Class<?>... parameterTypes)
获取本类种指定注解
Annotation getDeclaredAnnotations()
获取本类中所有注解