JAVA注解和反射

注解

何为注解

  • Annotation 是从JDK5.0开始引入的新技术
    JAVA注解和反射_第1张图片

作用:

Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。

格式

注解是以“@注释名”在代码中存在的,还可以添加一些参数值,例如:@SuppressWarnings(value=“unchecked”)

Annotation在哪里使用

可以附加在package、class、methdo、field等上面。相当于给他们添加了额外的辅助信息,我们可以通过反射机制实现对元数据的访问。

注解分类

JAVA注解和反射_第2张图片

标注注解

  • @Override:此注释只用适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明
  • @Deprecated:此注释修辞方法、属性、类。表示不鼓励程序猿使用这样的元素,通常是以为它很危险或存在更好的选择
  • @SuppressWarnings:用来抑制编译时的警告信息

元注解

元注解:修饰注解的注解,java定义了4个标准的meta-annotation类型。他们被用来提供对其他annitation类型的说明。

  • @Target:用于描述注解的使用范围(即:描述注解可以用在什么地方)
    JAVA注解和反射_第3张图片

  • @Retention:表示需要什么级别保存改注释信息,用于描述注解的生命周期
    (SOURCE JAVA注解和反射_第4张图片

  • @Document:说明改注册将被包含在javadoc中

  • @Inherited: 说明子类可以继承父类的注释

自定义注解

用户根据自己的需求自定义注解

注解解析

  • getDeclaredAnnotations :获得修饰的全部注册
  • getDeclaredAnnotation(Class annotationClass) :获得指定名称的注解
  • isAnannotationPreset(Class annotationClass) :判断是否存在此注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyAnnontation {
    String name() default "";
    String value();
}

@MyAnnontation(name ="aaaa",value = "bbbbb")
public class testAnontation {
    public testAnontation(){

    }

}

      Class<testAnontation> c= testAnontation.class;
        MyAnnontation declaredAnnotation = c.getDeclaredAnnotation(MyAnnontation.class);
        String name1 = declaredAnnotation.name();
        System.out.println(name1);

反射

动态语言

是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进。已有的函数可以被删除或是其他结构上的变化。通俗点就是运行时代码可以根据某些条件改变自身结构、
主要动态语言:Object-C、C#、JavaScript、PHP、Python

静态语言

与动态语言相对应,运行时结构不可变的语言就是静态语言。如Java、C、C++

Java不是动态语言。但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制获得类似动态语言的特性。Java的动态性让编程更加灵活。

反射定义

Reflection(反射)是Java被视为动态语言的关键。反射机制允许程序在执行期借助于Reflection API取的任何类的内部信息,并且能直接操作任意对象的内部属性及方法。
加载完类后,在堆内存的方法区中就产生一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类结构信息。我们可以通过这个对象看到类的结构。这个对象就想一面镜子。透过这个镜子看到类的结构。所有称之为反射

获取class 类的几种方式

  • 若已知具体的类,通过类的class属性获取,该防范最为安全可靠,程序性能更高。
Class clazz = Person.class;
  • 已知某类的实例,调用该实例的getClass()方法获取Class对象
Class clazz = person.getClass();
  • 已经一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取
Class clazz = Class.forName("demo01.Student");
  • 内置基本数据类型可以直接类名.Type
  • 还可以利用ClassLoader

类的加载

  1. 加载
    将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象
  2. 链接
    将Java类的二级制代码合并到JVM的运行状态之中的过程
    验证: 确保加载的类新复合JVM规范。没有安全方面的问题
    准备:正式为类变量(static)分配内存并设置类变量默认初始化值的阶段。这些内存都将在方法区中进行分配
    解析:虚拟机常量池的符号引用(常量名)替换为直接引用的过程。
  3. 初始化
    执行类的构造器()方法的过程。类构造器()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)
    当初始化一个类的时候,如果发现其父类还有没进行初始化,则需要其先触发父类的初始化
    虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步

什么时候会发生类初始化

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

类加载器

类加载器作用是把类(class)类装进内存。JVM规范定义了如下

  • 引导类加载器:用C++编写的,是JVM自带的类加载器,负责Java平台核心库。用来装载核心类库。该加载器无法直接获取。
  • 扩展类加载器:负责jre/lib/ext目录下的jar包或java.ext.dirs指定目录下的jar包装入工作库
  • 系统类加载器:负责java.class.path所指的目录下的类与jar包装入工作,是最常用的加载器。
    JAVA注解和反射_第5张图片

获取属性

  • getFields:获取public
  • getFields(String name):获取参数指定
  • getDeclaredFields:获取全部
  • getDeclaredFields(String name):获取带参

作用:赋值、取值

  • set(Object o,String str)
  • get(Object o)

获取构造方法

  • getConstructors:获取public修饰的构造方法
  • getConstructors(…param);获取public修饰的构造方法带参数
  • getDeclaredConstructor:获取所有的构造方法
  • getDeclaredConstructor(…param):获取所有的构造方法带参数

作用:构造器生成新对象

  • newInstance

获取方法

  • getMethods:获取public方法
  • getMethods(String name,…param):获取public方法,方法名、参数
  • getDeclaredMethods:获取所有方法,方法名、参数
  • getDeclaredMethods(String name,…param):获取所有方法,方法名、参数

作用:执行方法

  • invoke(Objecrt o,Object…args)

代理

动态代理

public interface Dosm {

    String sing();
}
public class Star implements Dosm {
    private String name;
    public  Star(String name){
        this.name=name;
    }

    @Override
    public String sing() {
        System.out.println(name+":唱歌");
        return "谢谢";
    }
}

newProxyInstance(ClassLoader loader,Class[] interfacesInvocationHandler h)

  • 参数1:用于指定一个类加载器
  • 参数2: 指定生成的代理长什么样子,也就是有哪些方法
  • 参数3: 用来指定生成的代理对象要干什么事情大
public class ProxyUtil {
    public static Dosm  createProxy(Star star){
       Dosm dosm= (Dosm) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{Dosm.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if("sing".equals(method.getName())){
                    System.out.println("先收钱");
                }
                String  str = (String) method.invoke(star);
                System.out.println(str);
                return  str;
            }
        });
        return  dosm;
    };
}

你可能感兴趣的:(java,开发语言)