注解和反射

注解和反射(缺少实例)

特注:本人跟着狂神学的

一、注解

1、什么是注解

注解叫Annotation,从JDK5.0开始引入的新技术

作用:

1.不是程序本身,但能够对程序做出解释(和注释差不多)

2.能够被其他程序(比如编译器)读取。

格式:

@注解名,还可以添加一些参数值

使用范围:包、类、方法、属性等都能使用,我们可以通过反射机制实现对于元数据的访问。

2、内置注解

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

@Deprecated:定义在java.lang.Deprecated中,此注解用于修饰方法、属性、类,表示不鼓励程序员使用这类元素,通常因为它很危险或者过时了或者有更好的选择。

@SuppressWarnings:定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息。与前两个注解不同,需要添加一个参数才能正确使用,这些参数都是已经定义好的:all(全部警告)、unchecked、deprecation

3、元注解

元注解的作用就是负责注解其他注解,Java定义了4个标准元注解类型,都在java.lang.annotation包中。

@Target:用于描述注解的适用范围(注解可以被用在那个地方)TYPE、FIELD、METHOD、CLASS...

@Retetion:表示在什么级别保存该注解信息,描述注解的生命周期:SOURCE<CLASS<RUNTIME(运行时)

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

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

4、自定义注解

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口。

特点:

1.@interface用来声明一个注解,格式:public@interface注解名{定义内容}

2.其中的每一个方法实际上是声明一个配置参数。

3.方法的名称就是参数的名称。

4.返回值类型就是参数的类型(返回值只能是基本类型、Class、String、enum)。int age() default 0;

5.可以使用default来声明参数的默认值。

6.如果只有一个参数成员,一般此参数名为value。

7.注解元素必须要有值,定义注解元素时,经常使用空字符串、0作为默认值。

二、反射机制

1、什么是反射?

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

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

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息,通过这个对象可以看到类的结构。这就像是一面镜子,能够看到内部的结构,所以称为反射。

2、Class类

所有的Object类中定义了以下的方法,此方法被所有的子类继承。

public final Class getClass()

以上方法返回值的类型是一个Class类,此类是java反射的源头

通过反射能够获得的信息:某个类的属性方法构造器、某个类到底实现了哪些接口,对于每个类而言,JRE都为其保留一个不变的Class类型的对象,一个Class对象包含了特定某个结构(class、interface、enum、annotation、ptimitive type、void、[])的有关信息。

注意

1.Class本身也是一个类

2.Class对象只能由系统建立对象

3.一个加载的类在JVM中只会有一个Class实力

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

5.每个类的实例都会记得自己是由哪个Class实例所生成

6.通过Class能够完整的得到一个类中的所有被加载的结构。

7.Class类是Reflection的根源,针对任何你想动态加载、运行的类唯有先获得相应的Class对象。

3、利用反射机制获得Class类对象

通过对象获得:person.getClass();

通过包路径名获得:Class.forName(String name);

通过类名获得:Class.class

反射中使用的方法:

static Class forName(String string) 返回指定类名name(包名)的Class对象

Object newInstance:调用缺省构造函数,返回Class对象的一个实例

getName():返回此Class对象所代表的实体(类,接口,数组类或void)的名称。

Class getSuperClass():返回当前Class对象的父类的Class对象

Class[] getingerfaces():返回当前Class对象的接口

ClassLoader getClassLoader():返回该类的类加载器

Constructor[] getConstructors():返回一个包含某些Constructor对象的数组

Method getMethod(String name,Class...T):返回一个Method对象,此对象的形参类型为paramType

Field[] getdeclaredFields():返回Filed对象的一个数组

哪些类型可以具有Class对象:class、interface、enum、annotation、ptimitive type、void、[]

3、类的加载

加载-链接-初始化

4、获取类的运行时结构

1.获得类名:

String c1.getName():获得包含包名的类名

String c1.getSimpleName():获得简单类名

2.获得属性

Field[] getFields:获得所有公开属性列表(public)

Field[] getDeclaredFields:获得所有属性列表

Field getField(String str):获得指定公开属性

Field getDeclaredField(String str):获得指定名称属性

3.获得方法

Method[] getMethods():获得本类及其父类全部public方法

Method[] getDeclaredMethods():获得本类所有方法

Method getMethod(String name,paramterTypes):获得指定方法(需要指定输入类型,以此避免重载情况)

4.获得构造器

Constructor[] getConstructors():获得本类公开的构造方法

Constructor[] getDeclaredConstructors():获得所有的构造方法

Constructor getConstructor(Class,Class):获得指定构造方法。

5、反射的应用

1.利用反射机制创建一个对象

利用类创建一个对象:

User user = (User)c1.**newInstance**();

调用无参构造创建,若无无参构造则失败。

利用构造器构造对象(可以有参可以无参)

Constructor con = c1.getConstructor(String.Class,int.Class);

User user2 = (User)con.newInstance("zhangsan",23);

2.利用反射机制调用普通方法

User user3 = (User)c1.newInstance();

Method setName = c1.getDeclaredMethod("setName",String.class)

setName.invoke(user3,"zhang");

3.利用反射机制操作属性

User user4 = (User)c1.newInstance();

Field name = c1.getDeclaredField("name");

name.setAccessible(true);//不能够直接访问私有属性,需要关闭程序安全检测

name.set(user4,"zhang");

6、性能对比

调用方法:

效率:普通方式>反射机制(关闭安全检测)>反射机制(未关闭安全检测)

7、反射操作泛型

Java采用泛型擦除的机制引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题,但是一旦编译完成,所有和泛型有关的类型全部擦除。

为了能够通过反射机制操作这种类型,Java新增了ParameterizedType、GenericArrayType、TypeVariable和WildcardType集中了欸行来代表不能被归一到Class类中的类型但是有何原始类名齐名的类型。

ParameterizedType:表示一种参数化类型,比如Collection

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

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

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

使用方法

Type[] method.getGenericParamterTypes():获得方法的泛型参数

Type[] method.getActualTypeArgument():获得泛型参数中的真实参数类型

Type[] method.getGenericReturnTypes():获得方法的泛型返回参数。

8、反射操作注解信息

使用方法

getAnnotations:

getAnnotation:

获取注解:

Annotation[] anno = c1.getAnnotations();

获取注解的value值:

zhang zhang = (zhang)c1.getAnnotation(zhang.class)//通过强转,获得指定注解;

String value = zhang.value();

获取类指定注解

Field field = c1.getDeclaredField("name")//获得指定属性

Fieldzhang anno = field.getAnnotation(Fielzhang.class);//获得指定属性的注解

system.out.print(anno.Name());//获得注解上的属性

system.out.print(anno.type);

system.out.print(anno.Name);

posted @ 2022-07-27 17:18  疯狂的豆包  阅读(43)  评论(0)    收藏  举报