注解与反射(基础)

注解

注解概念

注解 Annotation 可以对程序做出解释,与注释的区别是:注解可以被编译器读取,而注释不行,只是解释一段代码。

注解可以在packageclassmethodfield上使用,相当于给他们添加了额外的辅助信息,可以通过反射机制实现对这些元数据的访问。格式:@注解名 后面可以跟参数值

内置注解

@Override 修饰方法,表示是重写父类中的一个方法

@Deprecated 可修饰方法、属性、类 表示已经弃用的方法或类,不推荐使用,但是可以使用

@SuppressWarnings 用来抑制编译时的警告信息,需要传递参数才能使用

元注解

元注解就是负责对其他注解进行说明的注解 目前定义了四个

@Target 表示注解可以用在哪些地方

@Retention 表示注解在什么地方还有效(runtime运行 < class编译 > sources源码)

@Document 表示注解是否包含在Javadoc中

@Inherited 表示子类可以继承父类的注解

自定义注解

使用@interface 进行自定义注解 会自动继承 java.lang.annotation.Annotation接口

@interface 用来声明一个注解 其中的每一个方法实际上是声明了一个配置参数 方法名就是参数名

返回值类型就是参数类型,如果只有一个参数,一般参数名为value,注解元素必须要有值

在定义注解时,可以使用空字符串或者0 作为默认值

反射

静态语言与动态语言

动态语言就是一类在运行时可以改变其结构的语言,在运行时代码可以根据某些条件改变其自身结构,主要的动态语言有:C#、JavaScript、PHP、Python等

静态语言就是运行时结构不变的语言,如Java、C、C++等

反射概念

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

在加载完类之后,在堆内存的方法区会产生一个class类型的对象,包含了完整的类结构信息。可通过这个对象看到类的结构

通过对象反射出一个类的名字

反射的优缺点

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

缺点:对性能有影响,使用反射基本上是一种解释操作,相当于告诉JVM,希望他帮我们做什么,这类操作慢与直接执行相同的操作。

Class类

每个类都会有一个Class对象,这个Class对象包含了类的结构

Class本身已是一个类,一个加载的类在JVM中只会有一个Class实例,每个类的实例都会记得自己对应的Class对象。通过Class可以完整的得到一个类中的所有被加载的结构。

获取Class实例的方法

  • 若已知具体的类,通过类的class属性获取,最为可靠,程序性能最高

  • 已知某个类的实例,调用该对象的getClass()获取Class对象

  • 已知类的全类名,且该类在类路径下,可通过Class类的静态方法forname()来获取

  • 内置基本数据类型可直接用类名.Type

  • 利用ClassLoader

Java内存分析

在Java中,有三块存放内存的地方,分别是 堆内存、栈内存、方法区内存

堆内存

  • 存放new的对象和数组

  • 可以被所有的线程共享,不会存放别的对象引用

栈内存

  • 存放基本数据类型(包含这个基本类型的具体数值)

  • 引用对象的变量(会存放这个引用在堆里面的具体地址)

方法区内存

  • 可以被所有线程共享

  • 包含了所有的class和static变量

类的加载过程

类的加载过程分为三个阶段:类的加载、类的链接、类的初始化

类的加载

将类的class文件读入内存,创建Class对象,由类加载器完成

类的链接

将类的二进制数据合并到JRE中

类的初始化

JVM负责对类进行初始化

简单来说就是:

  1. 加载到内存,产生一个Class对象

  2. 链接,进行默认赋值

  3. 执行clinit()方法进行初始化

类的主动/被动引用

类的主动引用

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

  2. new一个类的对象

  3. 调用类的静态成员和静态方法(常量除外)

  4. 使用反射对类进行调用

  5. 当初始化一个类,若父类未初始化,先初始化父类

类的被动引用

当访问一个静态域,真正声明这个域的类会初始化,比如子类调用父类静态变量,不会对子类进行初始化

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

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

类加载器的作用

一个字节码文件加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后再堆中生成一个代表这个类的Class对象,作为方法区中类数据的访问入口。

类缓存 一旦类被加载到加载器中,它将维持加载一段时间,JVM的垃圾回收机制可以回收这些Class对象

使用反射执行对象方法

创建类的对象,可以通过调用Class对象的newInstance()方法来获得

执行方法:通过Method类完成,通过Class类的getMethod()获得一个Method对象,再调用Method对象的invoke()方法进行调用,传入的参数是 具体的哪个对象,以及方法需要的参数

如果方法的声明是private,需要在调用此方法之前,调用方法对象的setAccessible(true)方法,即可访问

setAccessible()作用的启动和禁用访问安全检查的开关,参数为true表示取消访问检查,设置为true之后,可提高反射的效率

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值