JAVA注解和反射

一、注解(Annotation):

  1、作用:

      不是程序本身,但可以对程序作出解释

      可以被其他程序读取

  2、格式:

      注解是以“@注释名”在代码中存在的,还可以添加一些参数值。如:@Override :重写

  3、使用方式:

      可以附加在package、class、method、field等上面,我们也可以通过反射机制实现对这些元数据的访问。

  4、内置注解:

      1、@Override:定义在java.lang.Override中,此注解是适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明。

      2、@Deprecated:定义在java.lang.Deprecated中,此注解可以用于修饰方法,属性,类(不推荐使用)

      3、@SuppressWarnings:定义在java.lang.SuppressWarnings中,用于来抑制编译时的警告信息

  5、元注解:

      元注解的作用就是负责注解其他注解,java定义了4个标准的meta-annotation类型,他们被用于提供对其他annotation类型说明。

        @Target:用于描述注解的使用范围

        @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期。(SOURCE<CLASS<RUNTIME)

        @Document:说明该注解将被包含在javadoc中

        @Inherited:说明子类可以继承父类中的该注解

package annotation;

import java.lang.annotation.*;

//测试元注解
@MyAnnotation
public class Test {
    public void test(){

    }

}

//定义一个注解
//Target:表示我们的注解可以用于那些地方
@Target(value = {ElementType.METHOD,ElementType.TYPE})

//Retention:表示我们的注解在什么地方有效    runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)

//
@Documented

@Inherited
@interface MyAnnotation{

}

  6、自定义注解:

      使用@interface自定义注解

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//自定义注解
public class Test1 {
    //注解可以显示赋值,如果没有默认值,我们就必须给注解赋值
    @MyAnnotation2(age = 10)
    public void t1(){
        
    }
    @MyAnnotation3("张三")
    public void t2(){

    }
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    //注解参数:参数类型+参数名();
    String name() default "";
    int age();
    int id() default -1; //如果默认值为-1,则表示不存在
    String[] schools() default ("hahah");

}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)

//如果一个注解只有一个参数,这参数名只能用value
@interface MyAnnotation3{
    String value(); 

}

 二、反射机制(Reflection):

  1、反射是java被视为动态语言的关键,反射机制允许程序在执行期间借助于反射API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

    加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个对象),这个对象就包含了完整的类的结构信息。我们可以通

    过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们称之为:反射。

          Class c=Class.forName("java.lang.String")

      

    2、反射机制提供的功能

      a、在运行时判断任意一个对象所属的类。

      b、在运行时构造任意一个类的对象

      c、在运行时判断任意一个类所具有的成员变量和方法

      d、在运行时获取泛型的信息

      e、在运行时调用任意一个对象的成员变量和方法

      f、在运行时处理注解

      g、生成动态代理AOP

       .....

    3、优缺点:

      a、优点:可以实现动态创建对象和编译,体现很大的灵活性

      b、缺点:对性能有影响。

package reflection;

//什么是反射
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的Class对象
        Class c1 = Class.forName("reflection.User");
        System.out.println(c1);
        
        Class c2 = Class.forName("reflection.User");
        Class c3 = Class.forName("reflection.User");
        Class c4 = Class.forName("reflection.User");
        //判断它们是否相等  
        //因此  一个类中只有一个Class对象
        //一个类被加载后,类的整个结构都会被封装在Class对象中
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());


    }


}
//实体类:pojo
class User{
    private String name;
    private int id;
    private int age;
    public User(){

    }

    public User(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

   4、Class类:

      1、Class本身也是一个类

      2、Class对象只能有系统建立对象

      3、一个加载的类在jvm中只会有一个Class实例

      4、一个Class对象对应的是一个加载到jvm中一个.class文件

      5、每个类的实力都会记得自己是有哪个Class实力所生成的

      6、通过Class可以完整地得到一个类中所有被加载的结构

      7、Class类是reflection的根源,针对任何的动态加载、运行的类,都唯有获得相应的Class对象

  5、Class类常用的方法

      

package reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test4 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("reflection.User");

        //获取类的名字
        System.out.println(c1.getName()); //获取到包名+类名
        System.out.println(c1.getSimpleName()); //获取到类名

        System.out.println("==============================");

        //获取类的属性
        Field[] fields=c1.getFields(); //只找到public属性
        fields=c1.getDeclaredFields(); //找到全部属性
        for (Field  field:fields){
            System.out.println(field);
        }

        System.out.println("==============================");

        //获取指定属性的值
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        System.out.println("==============================");

        //获取类的方法
        Method[] methods = c1.getMethods(); //获取本类及其父类的全部public方法
        for (Method method:methods){
            System.out.println("正常的:" + method);
        }
        methods = c1.getDeclaredMethods(); //获取本类的所有方法
        for (Method method:methods){
            System.out.println("DeclaredMethods:" + method);
        }

        System.out.println("==============================");

        //获取指定的方法
        //重载
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        System.out.println("==============================");
        //获取指定的构造器
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor:constructors){
            System.out.println(constructor);
        }
        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor:constructors){
            System.out.println("#"+constructor);
        }

        System.out.println("==============================");
        
        //获取指定的构造器
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println("指定的" + declaredConstructor);
    }
}

   6、获取Class类的实例:

    a、若已知具体类,通过类的class属性获取,该方法最为安全可靠,程序性能最高

        Class clazz=Person.class;

    b、已知某一个类的实例,调用该实例的getClass()方法获取Class对象

        Class clazz=person.getClass();

    c、已知一个类的全类名。且该类的类路径下,壳通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException

        Class clazz=Class.forName("demo01,Student")

    d、内置基本数据类型可以直接使用类名.Type

    c、还可以利用ClassLoader

package reflection;

//测试Class类的创建方式
public class Test1 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person=new Person();
        System.out.println("这个人是" + person);

        //方式一、通过getClass()对象获取
        Class c1 = person.getClass();
        System.out.println(c1);
        System.out.println(c1.hashCode());

        //方式二、通过forName()获取
        Class c2 = Class.forName("reflection.Student");
        System.out.println(c2);
        System.out.println(c2.hashCode());

        //方式三、通过类名.class获取
        Class c3= Student.class;
        System.out.println(c3);
        System.out.println(c3.hashCode());

        //方式四、基本内置类型的包装类都有一个Type属性
        Class c4 = Integer.TYPE;
        System.out.println(c4);

        //获取父类类型
        Class C5 = c1.getSuperclass();
        System.out.println(C5);


    }
}
class Person{
     String name;
     public Person(){

     }
    public Person(String name) {
        this.name = name;
    }
}
class Student extends Person{
    public Student(){
        this.name="学生";
    }
}
class Teacher extends Person{
    public Teacher(){
        this.name="老师";
    }
}
package reflection;

import java.lang.annotation.ElementType;

//所有类型的Class对象
public class Test2 {
    public static void main(String[] args) {
        Class c1 = Object.class;//
        Class c2 = Comparable.class;//接口
        Class c3 = String[].class;//一维数组
        Class c4 = int[][].class;//二维数组
        Class c5 = Override.class;//注解
        Class c6 = ElementType.class;//枚举
        Class c7 = Integer.class;//基本数据类型
        Class c8 = void.class;//void
        Class c9 = Class.class;//Class

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);

        //只有元素类型与维度一样,就是同一个Class
        int[] a=new int[10];
        int[] b=new int[20];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());


    }
}

动态创建对象

package reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


//动态的创建对象,通过反射
public class Test5 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获取class对象
        Class c = Class.forName("reflection.User");

        //构造一个对象
        User user = (User)c.newInstance(); //本质调用了类的无参构造
        System.out.println(user);
        System.out.println("=====================================");

        //通过构造创建对象
        Constructor constructor = c.getDeclaredConstructor(String.class, int.class, int.class);
        User user1 = (User)constructor.newInstance("zy", 2021, 02);
         System.out.println(user1);
        System.out.println("=====================================");

        //通过反射调用普通方法
        User user2 = (User) c.newInstance();

        //通过反射获取一个方法
        Method setName = c.getDeclaredMethod("setName", String.class);
        //invoke : 激活的意思
        //invoke(对象,"方法的意思")
        setName.invoke(user2,"哈哈哈");
         System.out.println(user2.getName());
        System.out.println("=====================================");

        //通过反射操作属性
        User user4 =(User)c.newInstance();
        Field name = c.getDeclaredField("name");
        //不能直接操作私有属性,我们需要关闭程序的安全检测,
            //因此要加上属性或者方法的setAccessible(true)
        name.setAccessible(true);
        name.set(user4,"java");
        System.out.println(user4.getName());


    }
}

   7、反射操作泛型:

    ~ParameterizedType:表示一种参数化类型,比如:Collenction<String>

    ~GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型

    ~TypeVariable:是各种类型变量的公共父接口

    ~WildcardType:代表一种通配符类型的表达式

package reflection;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

//反射操作泛型
public class Test6 {
    public void test01(Map<String,User> map, List<User> list){
        System.out.println("test01");
    }
    public Map<String,User> test02(){
        System.out.println("test02");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Test6.class.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("#" + genericParameterType);
            if (genericParameterType instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }
         method = Test6.class.getMethod("test02", null);
        Type genericReturnType = method.getGenericReturnType();
            if (genericReturnType instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }

    } 

  8、反射获取注解信息:

package reflection;

import java.lang.annotation.*;
import java.lang.reflect.Field;

//反射获取注解信息
public class Test7 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("reflection.Student2");

        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);

        }
        //获得注解的value的值
        TableStudent tableStudent = (TableStudent) c1.getAnnotation(TableStudent.class);
        String value = tableStudent.value();
        System.out.println(value);

        //获取类指定的注解
        Field f = c1.getDeclaredField("name");
        FieldStudent annotation = f.getAnnotation(FieldStudent.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }

}
@TableStudent("db_student")
class Student2{
    @FieldStudent(columnName = "db_id",type ="int",length =10)
    private int id;
    @FieldStudent(columnName = "db_name",type ="String",length =2)
    private String name;
    @FieldStudent(columnName = "db_age",type ="int",length =10)
    private int age;

    public Student2() {
    }

    public Student2(int id, String name, int age) {

        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableStudent{
    String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldStudent{
    String columnName();
    String type();
    int length();
}   

  9、类的加载(ClassLoader)

      加载——>连接——>初始化(<clinit>())

    a、类的初始化什么时候发生?

        1、类的主动引用(一定会发生类的初始化)

            ~当虚拟机启动,先初始化main方法所在的类

            ~new一个类的对象

            ~调用类的静态成员(除了final常量)和静态方法

            ~使用java.lang.reflect包的方法对类进行反射调用

            ~当初始化一个类,如果其父类没有被初始化,则先初始化它的父类

        2、类的被动引用(不会发生类的初始化)

            ~当访问一个静态域时,只有真正声明这个域才会被初始化,如:当通过子类引用父类的静态变量,不会导致子类初始化

            ~通过数组定义类引用,不会触发此类的初始化

            ~引用常量不会触发此类的初始化(常量在连接阶段就存入调用类的常量池中了)

package reflection;


import java.util.SortedMap;

//类的初始化什么时候发生?
public class Test3 {
    static {
        System.out.println("main被加载");
    }
    public static void main(String[] args) throws ClassNotFoundException {
        //1、主动引用
           // Son son = new Son();
        //反射也会主动引用
           //Class.forName("reflection.Son");
        
        //2、不会产生类的引用的方法
        
      //  System.out.println(Son.b);
       // Son[] array=new Son[5];
        System.out.println(Son.M);
    }
}
class Father{
   static int b=2;
   static {
       System.out.println("父类被加载");
   }
}
class Son extends Father{
    static {
        System.out.println("子类被加载");
        m=300;
    }
    static int m=100;
    static final int M=1;
}

 

 

 

  

 

      

posted @ 2021-02-15 20:52  年华只余一地悲凉  阅读(40)  评论(0编辑  收藏  举报
/*粒子线条,鼠标移动会以鼠标为中心吸附的特效*/