反射和注释
Posted 陈鹏烨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射和注释相关的知识,希望对你有一定的参考价值。
一、反射
用途:开发工具、框架等。比如开发Hibernate、依赖注入就是用反射技术 来生成一套代码。
所以,反射最大特点是针对通用编程,避免了硬编码。
1. 类对象 类加载
Class 类对象(封装类的信息)
例如Student.class Teacher.class 在虚拟机中
编译后.class文件为类的信息在JVM中的体现:
例如,动物园每类动物都有一个介绍牌子,介绍的是该类的信息。
牌子是一个描述该类信息的对象,即动物类的类对象。
区分概念:(以下类比帮助理解)
类 狼
对象 类的对象,就是一只狼
类对象 牌子,牌子类的对象
类类 牌子类
如何获得一个类的类对象?有如下三中方法:
(1) Class c1=String.class; //类名加.class 前提为知道类名
(2) Student s1=new Student(“Liucy”); //通过类的对象得到类对象
Class c2=s1.getClass(); //得到Student所属类的类对象
例如:
String s1=”123”;
String s2=”456”;
Class c1=s1.getClass();
Class c2=s2.getClass(); c1==c2的判断结果为true. 全类只有一个类对象
最常见也最灵活的方式:
(3) String className=”java.lang.String”; //用字符串当参数
Class c3=Class.forName(className); //静态方法。 会发生类加载
有可能此类未被加载,则要先加载(通过类名找到文件加载),再返回类对象
注意:类名应写全限定名。即包名+类名
使用场合为类名存在字符串中时。
2.Java类反射中的主要方法 详见TestClass.java TestReflection.java程序
对于以下两类组件中的任何一类来说 -- 构造函数和方法 -- java.lang.Class 提供四种独立的反射调用,以不同的方式来获得信息。调用都遵循一种标准格式。
以下是用于查找构造函数的一组反射调用:
Constructor getConstructor(Class[] params) 获得使用特殊的参数类型的公共构造函数
Constructor[] getConstructors() -- 获得类的所有公共构造函数
Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数
Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数
用于获得方法信息函数:
Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法
Method[] getMethods() -- 获得类的所有公共方法
Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法
Method[] getDeclaredMethods() -- 获得类声明的所有方法
3.反射更大的功能: 通过类对象,得到类的对象。能操纵这个类。
对类对象调用 newInstance() 则用无参构造方法构造一个其对象
Object o1=new Student(); //直接生成
?
Class c1=Class.forName(“Student”);
Object o2=c1.newInstance();
通过类对象获得类的对象 “通过狼的牌子得到一只小狼”
Student s2=new Student(“Liucy”); ?
s2.study(“CoreJava”);
| |
一般步骤:
Step1: 通过类名获得类对象
Class c=Class.forName(“Student”);
Step2: 获得我们想要的构造方法对象Constructor Object
Class[] paramenters={ String.class }; // 返回Class[] 数组
Constructor con=c.getConstructor(paramenters); //类对象数组作为参数
Step3: 调用构造方法,创建对象
Object[] os={“Liucy”};
Object o=con.newInstance(os);
Step4: 获得想要调用的方法对象 用getMethod( 方法名,Class[] )
Method m=c.getMethod(“study”, parameters);
Step5: 对创建好的对象调用指定的方法
Object[] os2={“CoreJava”};
m.invoke(o, os2); //针对o类调用m方法,传入的是os2参数
二、注释 Annotation
描述代码的代码 给机器看的
一个注释也是一个类型。 类、接口、枚举均为类型
要求:会通过查找API进行注释的使用。
在API的 Annotation Type 中
注释分类:
1. 标记注释
@Override //描述此代码要覆盖父类的方法
@Deprecated //告诉编译器该类或方法是过期的,告诉不提倡使用(编译器会发出警告)
2. 单值注释 只有一个属性的注释
@注释名(para=”123”)
(value=20.123); //value= 可以不写。 两个前提条件:1 为单值; 2 属性为value
@SuppressWarnings({“A”,”B”,”C”}) //抑制警告. 用{}表示一个String[] 省略了value=
此注释是规范中提出的标准,但还没提供支持。
3. 普通注释 多值注释,逗号隔开
@注释名(para1=”123”, para2=”456”, ... )
给方法、属性、构造方法、类 加注释
==============================================
自己写注释:(分三块)
①注释注释 给注释添加注释(元注释) 需要引入java.lang.annotation.*包
共四种:Documented Inherited Retention Target
Target 定义了将来能注释什么,单值注释
@Target(value={ElementType.METHOD}) //表示能给方法加注释
@Target(value={ElementType.METHOD, ElementType.CONSTRICTPR })
枚举常量
ANNOTATION_TYPE 注释类型声明
CONSTRUCTOR 构造方法声明
FIELD 字段声明(包括枚举常量)
LOCAL_VARIABLE 局部变量声明
METHOD 方法声明
PACKAGE 包声明
PARAMETER 参数声明
TYPE 类、接口(包括注释类型)或枚举声明
Retention 表示此注释会被保留到什么时候。 是给编译器用的。
@Retention(value=RetentionPolicy.RUNTIME) //平时必须得是RUNTIME
枚举常量
CLASS 编译器将把注释记录在类文件中,但在运行时虚拟机不需要保留注释。
RUNTIME 不仅保存在.class文件中,而且JVM中还会加载入。
SOURCE 只会被保留在源文件中,生成.class文件就被滤掉了。
Documented 、 Inherited 用的极少
②注释定义 注释本质是接口 Interface Annotation 的子接口
public @interface TestCase{ //定义一个注释
String parameter() default “Liucy”; //提供注释属性,并且提供默认值
}
注释属性类型: 8种简单数据类型
String
Enum
Annotation
Class 以及以上的数组。共24种。
查看TestEngine.java 课堂例子
③注释分析
查看MyClass.java
以上是关于反射和注释的主要内容,如果未能解决你的问题,请参考以下文章