和我一起迎接明天的太阳吧

klaus08

焦虑源于行动的匮乏

注解和反射

注解


内置注解

  1. @Deprecated

    // @Deprecated 意思是不推荐使用
    @Deprecated
    public static void test(){
    
    }
    

    使用@Deprecated注解的方法在使用时会有这种提示。


  1. @Override

    // @Override 重写父类的方法
    @Override
    public String toString() {
        return super.toString();
    }
    

  2. @SuppressWarnings
    镇压警告

    @SuppressWarnings("all")
    

元注解( meta-annotation )

元注解的作用就是注解其他注解,Java 定义了 4 个标准的 meta-annotation 类型。

  • @Target:描述注解的作用范围
  • @Retention:表示需要在什么级别保存保存该注释信息,用于描述注解的生命周期。
    (Source < Class < Runtime)
  • @Document:说明该注解将被包含在 javadoc 中
  • @Inherited:说明该类的子类可以继承父类的注解

自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    int id();
    String name() default "klaus";
}


反射



一个类在内存中只有一个 Class 对象
一个类被加载后,类的整个结构都被封装在 class 中

package com.klaus.reflection;


// 什么是反射
public class Test extends Object{
    public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Class.forName("com.klaus.reflection.USer");
        Class c2 = Class.forName("com.klaus.reflection.USer");
        Class c3 = Class.forName("com.klaus.reflection.USer");
        Class c4 = Class.forName("com.klaus.reflection.USer");

		// 哈希值相同
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());


    }
}


class USer{
}

获取 class 的方法

package com.klaus.reflection;

public class Test2 {

    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这个人是" + person.name); //这个人是学生

        //1. 通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());//460141958

        //2.forName
        Class c2 = Class.forName("com.klaus.reflection.Student");
        System.out.println(c2.hashCode());//460141958

        //3.通过类名.class获得
        Class c3 = Student.class;
        System.out.println(c3.hashCode());//460141958

        //4.基本内置类型有 Type方法
        Class c4 = Integer.TYPE;
        System.out.println(c4);//int

        //5.获得class的父类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);//class com.klaus.reflection.Person
    }

}
class Person{
    String name;

    public Person() {}
}

class Student extends Person{
    public Student() {
        this.name = "学生";
    }
}

class Teacher extends Person{
    public Teacher(){
        this.name = "老师";
    }
}


类的初始化


类的主动引用一定会发生类的初始化

  • 虚拟机启动,先初始化 main 方法所在的类
  • new 一个对象
  • 使用类的静态成员(除了 final 常量)和静态方法
  • 使用 java.lang.reflect 包的方法进行反射调用
  • 初始化一个类,如果父类没有被初始化,那么先初始化父类

被动引用

  • 访问一个静态域时,只有真正声明它的类才会被初始化
  • 通过数组定义类引用,不会触发此类的初始化(比如说定义了一个对象类型的数组)
  • 引用常量不会触发类的初始化(常量在链接阶段就存入常量池了)


反射的使用


Class c1 = Class.forName("com.klaus.reflection.User");

无参构造动态创建对象

// 无参构造
User user = (User) c1.newInstance();
System.out.println(user); / /USer{name='null', id=0, age=0}

有参构造创建对象

// 有参构造Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);User instance =(User) constructor.newInstance("klaus", 12, 2);System.out.println(instance);// USer{name='klaus', id=12, age=2}

通过反射调用方法

//通过反射调用方法Method setName = c1.getDeclaredMethod("setName", String.class);// 获得方法setName.invoke(instance,"Klaus08");System.out.println(instance);//USer{name='Klaus08', id=12, age=2}

通过反射操作属性

//通过反射操作属性,对于私有属性要关闭 “安全检测”User user2 =(User) c1.newInstance();Field name = c1.getDeclaredField("name");name.setAccessible(true);name.set(user2,"zoe");System.out.println(user2.getName()); //zoe

全部代码如下:

package com.klaus.reflection;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;// 动态创建对象public class Test7 {    public static void main(String[] args) throws Exception {        Class c1 = Class.forName("com.klaus.reflection.User");        // 无参构造        User u = (User) c1.newInstance();        System.out.println(u);        // 有参构造        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);        User instance =(User) constructor.newInstance("klaus", 12, 2);        System.out.println(instance);        //通过反射调用方法        Method setName = c1.getDeclaredMethod("setName", String.class);// 获得方法        setName.invoke(instance,"Klaus08");        System.out.println(instance);        //通过反射操作属性,对于私有属性要关闭 “安全检测”        User user2 =(User) c1.newInstance();        Field name = c1.getDeclaredField("name");        name.setAccessible(true);        name.set(user2,"zoe");        System.out.println(user2.getName());    }}

setAccessible



反射&注解


通过反射获得注解信息,下面的代码演示了一般 ORM 注解的原理,通过注解获得属性对应列名,使 pojo 和表联系起来。

package com.klaus.reflection;import java.lang.annotation.*;import java.lang.reflect.Field;public class Test8 {    public static void main(String[] args) throws Exception {        Class c1 = Class.forName("com.klaus.reflection.Student_");        //通过反射获得注解        Annotation[] annotation = c1.getAnnotations();        for (Annotation annotation1 : annotation) {            System.out.println(annotation1);//@com.klaus.reflection.TableKlaus(value=stu)        }        TableKlaus tableKlaus = (TableKlaus)c1.getAnnotation(TableKlaus.class);        String value = tableKlaus.value();        System.out.println(value);//stu        Field name = c1.getDeclaredField("name");        ColumnKlaus columnKlaus = name.getAnnotation(ColumnKlaus.class);        System.out.println(columnKlaus.column());//name        System.out.println(columnKlaus.type());//type    }}@TableKlaus("stu")class Student_{    @ColumnKlaus(column ="name",type = "String")    String name;    @ColumnKlaus(column = "id", type = "int")    int id;}// 类的注解@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interface TableKlaus{    String value();}// 属性注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface ColumnKlaus{    String column();    String type();}
posted @ 2021-08-12 12:27  klaus08  阅读(31)  评论(0编辑  收藏  举报