反射:
枚举反射泛型注解.html
34.3 KB
34.3 KB
反射, 主要是指通过类加载, 动态的访问, 检测和修改类本身状态或行为的一种能力, 并能根据自身行为的状态和结果, 调整或修改应用所描述行为的状态和相关的语义。
反射操作核心的概念“一切的操作都将使用Object完成, 类、 数组的引用都可以使用Object进行接收”
实例化类对象的方式。
1。 Class> c1 = Class . for Name( " 完整的类路径") 常用
2。 Class>c2 =类名.class
3。 Class>c3 =new 类名( ).getClass( )
Class 类常用操作
1 getSimpleName()获取类名 2 getName()获取完整的“包,类”名称; 3 Class 类的使用 4 无参构造实例化对象 5 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, 6 IllegalAccessException { 7 //通过类路径获取类Class对象 8 Class> clazz = Class.forName("com.project.enmutestdemo.fanshe.Person"); 9 //调用newInstance()方法, 调用无参构造创建类对象 10 Person person = (Person) clazz.newInstance(); 11 //操作对象 12 person.setAge(12); 13 person.setName("张三"); 14 System.out.println(person); 15 } 16 有参构造实例化对象 17 public static void main(String[] args) throws ClassNotFoundException, 18 InstantiationException, IllegalAccessException, 19 IllegalArgumentException, InvocationTargetException { 20 //获取类的Class对象 21 Class> clazz =clazz.forName("com.project.enmutestdemo.fanshe.Person"); 22 //通过参数类型获取类的具体的某一个构造器 23 Constructor> c = clazz.getConstructor(String.class,int.class); 24 Person person = null; 25 // 传入实参, 通过构造器创建类对象 26 person = (Person) c.newInstance("张三", 20); 27 System.out.println(person);
Constructor 构造器类 常用的方法
Field 类常用方法
1 getmodified 获取访问修饰符(public private 。。。) 2 取得类中属性 3 public static void main(String[] args) throws ClassNotFoundException { 4 Class> clazz = null; 5 //通过类路径获取类Class对象 6 clazz = Class.forName("com.project.enmutestdemo.fanshe.Person"); 7 //取得本类的属性 8 Field[] f = clazz.getDeclaredFields(); 9 //循环操作类的属性 10 for(int i = 0; i < f.length; i++){ 11 //取得该属性的类型 12 Class> t = f[i].getType(); 13 //取得该属性的修饰符数字 14 int mo = f[i].getModifiers(); 15 //通过修饰符数字取得属性的修饰符 16 String priv = Modifier.toString(mo); 17 System.out.print("本类属性: "); 18 System.out.print(“ 修饰符为: ”+priv+" "); 19 System.out.print(“类型为: ”+t.getName()+" "); 20 System.out.print(“名称为: ”+f[i].getName()+”\n”); 21 22 23 通过反射 操作属性 24 //获取类的Class对象 25 Class> clazz = Class.forName("com.project.enmutestdemo.fanshe.Person"); 26 //调用无参构造器创建类对象 27 Object obj = clazz.newInstance(); 28 //通过属性名称获取属性的Field对象 29 Field nameFiled = clazz.getDeclaredField("name"); 30 //通过set方法对对象的属性进行赋值 31 nameFiled.set(obj, "张三"); 32 //通过get方法获取对象的属性值 33 System.out.println(" 姓名: "+nameFiled.get(obj)); 34 35 操作类中的属性 36 //获取类的Class对象 37 Class> clazz = Class.forName("com.project.enmutestdemo.fanshe.Person"); 38 //调用无参构造器创建类对象 39 Person obj = clazz.newInstance(); 40 //通过属性名称获取属性的Field对象 41 Field nameFiled = clazz.getDeclaredField("name"); 42 //设置该属性的访问权限为可访问 43 nameFiled.setAccessible(true); 44 //通过set方法对对象的属性进行赋值 45 nameFiled.set(obj, "张三"); 46 //通过get方法获取对象的属性值 47 System.out.println(" 姓名: "+nameFiled.get(obj));
Method 类常用方法
1 取得类的全部方法 2 //获取类的Class对象 3 Class> clazz = Class.forName("com.project.enmutestdemo.fanshe.Person"); 4 Method[] method = clazz.getDeclaredMethods();//获取本类所有方法 5 for(int i = 0; i < method.length;i++){//循环操作方法 6 Class> r = method[i].getReturnType();//获取方法的返回值类型 7 Class> p[] =method[i].getParameterTypes();//获取方法的参数类型 8 int xx = method[i].getModifiers();//获取方法的修饰符数字 9 System.out.print(Modifier.toString(xx)+" ");//获取修饰符 10 System.out.print(r.getSimpleName()+" ");//获取方法返回值类型名称; 11 System.out.print(method[i].getName());//获取方法名称 12 System.out.print("("); 13 for(int x = 0; x < p.length;x++){//循环操作参数类型 14 System.out.print(p[x].getSimpleName() +" "+ "arg"+x);//输出参数 15 if(x < p.length -1){//判断是否输出“ , ” 16 System.out.print(",");//输出“ , ” 17 } 18 }S 19 ystem.out.println();//换行 20 } 21 调用类中的方法 22 public static void main(String[] args) throws ClassNotFoundException, 23 NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, 24 InvocationTargetException, InstantiationException { 25 //获取类的Class对象 26 Class> clazz = Class.forName("com.project.enmutestdemo.fanshe.Person"); 27 //通过方法名称获取无参Method对象 28 Method me = clazz.getMethod("speak"); 29 //调用无参构造器创建类对象 30 Object obj = clazz.newInstance() 31 me.invoke(obj); 32 33
利用反射,在控制台输出以下信息:
public class UserPo{
private int id;
private String userName;
private String userPass;
}
注解:
给程序 看的注释, 称为 注解(Annotation) 是代码里的特殊标记,可以在编译,类加载,运行时被读取,并执行相应的处理。 通过使用注解,可以在不改变原有的逻辑的情况下,在源文件嵌入一些补充的信息。
Annotation 提供为程序元素 (包,类,构造器,方法,成员变量,参数,局部变量)设置 元数据的方法 , 它不能运行,只有成员变量,没有方法,跟修饰符一样地位
基本 Annotation :
@Override 限定重写父类方法,如果存在,则正确,反之 ,报错
@Deprecated 表示某个程序或元素 已过时。
@SuppressWaring:抑制编译器警告;
@SafeVarargs:是JDK7专门为抑制“堆污染”警告提供的;
自定义 注解
定义新的Annotation 类型使用@interface 关键字,例如
Public @interface Table{
}
使用 Annotation 一般会放在另一行,并且放在修饰符之前,如
@Table
public class Myclass{
。。。。
}
成员变量声明
1 无形参的方法
public @interface MyTag {
string name();
int age ();
}
2 指定默认值 在指定成员变量时,使用default 关键字
public @interface MyTag{
string name ()default “ 张三” ;
int age () default 18;
}
成员变量的使用方式
1 无形参方法声明时
public class AnnonationTest{
@MyTag ( name = "张三",age=30)
public void info(){
...
}
}
2 默认值声明变量时
public class AnnonationTest{
@MyTag
public void info(){
}
}
Annoation 分类
根据 Annotation 是否包含成员变量, 我们把其分为两类
1 没有成员变量的: 标记Annotation 仅用自身的存在与否提供信息 如重写
2 包含成员变量的: 元数据 Annotation
元注解 (注解的注解)
@Retention : 用于指定 Annotation 可以保留多长时间
@Target : 指定 Annotation 用于修饰那些元素
@Documented: 用于被修饰的Annotation类将被javadoc工具提取成文档,
默认情况下,javadoc是不包括注解的。
@Inherited:指定Annotation具有继承性;
@Retention(RetentionPolicy.RUNTIME)//元注解
@Target(ElementType.TYPE)//元注解 都是修饰下面的Table 自定义注解的注解
public @interface Table { // 自定义注解
String name();
}
@Column(name = "name")
String name;
@Column(name = "age")
int age;
注解同public 地位一样,同属性绑在一起,可以通过反射Field(属性)操作注解
@Retention
包含一个名为value 的成员变量 , 是RetentionPolicy枚举类型 值如下
RetentionPolicy.SOURCE:Annotation只保留在源代码中,编译器编译时,
直接丢弃这种Annotation;
RetentionPolicy.RUNTIME:编译器把Annotation记录在class文件中。当运行java程序时,JVM会保留该Annotation,程序可以通过反射获取该Annotation的信息;
RetentionPolicy.CLASS:编译器把Annotation记录在class文件中。当运行
java程序时,JVM中不再保留该Annotation;
@Target
包含一个名为“value”的成员变量, 该value成员变量类
型为ElementType[],ElementType为枚举类型, 其值为:
ElementType.TYPE:能修饰类、接口或枚举类型;
ElementType.FIELD:能修饰成员变量;
ElementType.METHOD:能修饰方法;
ElementType.PARAMETER:能修饰参数;
ElementType.CONSTRUCTOR:能修饰构造器;
ElementType.ANNOTATION_TYPE:能修饰注解;
ElementType.LOCAL_VARIABLE:可用于局部变量上
ElementType.PACKAGE:用于记录java文件的package信息
提取Annotation 信息
JDK主要提供两个类, 来完成Annotation的提取:
java.lang.annotation.Annotation接口:所有 annotation 类型都要扩展的公共接口;
java.lang.reflect.AnnotatedElement接口:该接口允许反射性地读取注解。
java.lang.reflect.AnnotatedElement接口
isAnnotationPresent(Class extends Annotation> annotationClass):判断该程序元素上是否存在指定类型的注解,如果存在则返回true,否则返回false;
getAnnotation(Class annotationClass):返回该程序元素上存在的指定
类型的注解,如果该类型的注解不存在,则返回null;
Annotation[] getAnnotations():返回该程序元素上存在的所有注解;
Annotation[] getDeclaredAnnotations() :返回直接存在于此元素上的所有注解。
通过反射取得Annotation
取得指定的Annotation ;