注解、反射机制

一、注解(Annotation)

作用:

  • 不是程序本身,可以对程序做出解释。(同注释)
  • 可以被其他程序读取。
    格式
    @注解名
    在哪里使用
    可以附加在package、class、method、field(属性)上面,相当于给他们添加了额外的辅助信息。

内置注解

@Override 重写
@Deprecated 废弃,不鼓励使用,危险或存在更好的选择
@SuppressWarnings 抑制编译时的警告信息

自定义注解

  • @interface用来声明一个注解
    格式: public @interface 注解名(定义体)
  • 每一个方法实际上时声明了一个配置函数
  1. 方法的名称就是参数的名称
  2. 返回值类型就是参数的类型(类型只能是基本类型、Class、String、enum)
  3. 可以通过default来声明参数的默认值
  4. 如果只有一个参数成员,一般参数名为value

注意: 注解元素必须要有值。可使用空字符串、0作为默认值,也常使用负数(如:-1)表示不存在的含义

元注解

负责注解其他注解。Java定义了4个标准的meta-annotation类型

  • @Target
  • @Retention
  • @Documented
  • @Inherited

@Target

作用: 用于描述注解的适用范围

所修饰范围 取值 ElementType
package PACKAGE
类、接口、枚举、Annotation TYPE
类型成员(方法、构造方法、成员变量、枚举值) CONSTRUCTOR:构造器、FIELD:属性、METHOD:方法
方法参数和本地变量 LOCAL_VARIABLE:局部变量、PARAMETER:参数|

例:

@Target(value={
     ElementType.METHOD,ElementType.TYPE})
//value可为数组

@Retention

作用: 表示需要在什么级别保存该注释信息,用于描述注解的生命周期

取值 RetentionPolicy 作用
SOURCE 在源文件中有效
CLASS 在class文件中有效
RUNTIME 在运行时有效,为Runtime可以被反射机制读取

二、反射机制(Reflection)

  • 指的是可以于运行时加载、探知、使用编译期间完全未知的类

  • 程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已加载的类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;

      Class c = Class.forName(类名)
    

获取方式

//1.
Class clazz = Class.forName(类名);
//2.
Class clazz = 类名.class;
//3.
Class clazz = 对象.getClass();

常见作用

  1. 动态加载类、动态获取类的信息(属性、方法、构造器)
  2. 动态构造对象
  3. 动态调用类和对象的任意方法、构造器
  4. 动态调用和处理属性
  5. 获取泛型信息
  6. 处理注解

1. 动态加载类、动态获取类的信息(属性、方法、构造器)

public static void main(String[] args) {
     
	String path = "Reflection.User";
	
	try {
     
		Class<?> clazz = Class.forName(path);
		
		//获取类的名字
		System.out.println("getName()输出:"+clazz.getName());
		System.out.println("getSimpleName()输出:"+clazz.getSimpleName());
		
		//获取属性信息
		Field[] fields1 = clazz.getFields();	//只能获得public的属性
		System.out.println("public属性个数:"+fields1.length);
		Field[] fields2 = clazz.getDeclaredFields();	//所有属性
		System.out.println("属性个数:"+fields2.length);
		for(Field temp:fields2) {
     
			System.out.println("属性:"+temp);
		}
		Field f = clazz.getDeclaredField("uName");
		
		//获取方法信息
		Method[] methods = clazz.getDeclaredMethods();
		//如果方法有参,则必须传递参数类型对应的class对象
		Method m1 = clazz.getDeclaredMethod("getuName",null);
		Method m2 = clazz.getDeclaredMethod("setuName",String.class);
		for(Method temp:methods) {
     
			System.out.println("方法:"+temp);
		}
		
		//获取构造器信息
		Constructor[] constructors = clazz.getDeclaredConstructors();
		for(Constructor temp:constructors) {
     
			System.out.println("构造器:"+temp);
		}
		Constructor c = clazz.getDeclaredConstructor(null);
	} catch (Exception e) {
     
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}	

输出结果
注解、反射机制_第1张图片

2. 通过反射API动态的操作:构造器、方法、属性

public static void main(String[] args) {
     
		
	String path = "Reflection.User";
		
	try {
     
		Class<User> clazz = (Class<User> )Class.forName(path);
		
		//通过反射API动态调用构造方法,构造对象
		//调用User的无参构造方法
		User u1 = clazz.getDeclaredConstructor().newInstance();
		
		//调用User的有参构造方法
		User u2 = clazz.getDeclaredConstructor(int.class,int.class,String.class).newInstance(1001,18,"abc1");
		System.out.println(u2.getuName());
		
		//通过反射API调用普通方法
		User u3 = clazz.getDeclaredConstructor().newInstance();
		Method method = clazz.getDeclaredMethod("setuName", String.class);
		method.invoke(u3, "abc2");
		System.out.println(u3.getuName());
		
		//通过反射API操作属性
		User u4 = clazz.getDeclaredConstructor().newInstance();
		Field f = clazz.getDeclaredField("uName");
		f.setAccessible(true);	//这个属性不需要做安全检查,可以直接访问
		f.set(u4, "abc3");		//通过反射直接写属性
		System.out.println(u4.getuName());
		System.out.println(f.get(u4));			//通过反射直接读属性的值
		
	} catch (Exception e) {
     
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

3. 反射操作泛型(Generic)

public static void main(String[] args) {
     
	try {
     
		//获得指定方法参数泛型信息
		System.out.println("---------获得指定方法参数泛型信息---------");
		Method m1 = Demo4.class.getMethod("test01", Map.class,List.class);
		Type[] t = m1.getGenericParameterTypes();
		for(Type paramType:t ) {
     
			System.out.println("#"+paramType);
			if(paramType instanceof ParameterizedType) {
     
				Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
				for(Type genericType:genericTypes) {
     
					System.out.println("参数泛型类型:"+genericType);
				}
			}
		}
		
		//获得指定方法返回值泛型信息
		System.out.println("\n---------获得指定方法返回值泛型信息---------");
		Method m2 = Demo4.class.getMethod("test02", null);
		Type returnType = m2.getGenericReturnType();
		System.out.println("#"+returnType);
		if(returnType instanceof ParameterizedType) {
     
			Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
			for(Type genericType:genericTypes) {
     
				System.out.println("返回值泛型类型:"+genericType);
			}
		}
	} catch (Exception e) {
     
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

注解、反射机制_第2张图片

4. 反射操作注解(Annotation)

public static void main(String[] args) {
     
	try {
     
		Class clazz = Class.forName("Reflection.MyStudent");
		
		// 获得类的所有有效注解
		System.out.println("---------获得类的所有有效注解---------");
		Annotation[] annotations = clazz.getAnnotations();
		for (Annotation a : annotations) {
     
			System.out.println(a);
		}
		
		// 获得类的指定注解
		System.out.println("\n---------获得类的指定注解---------");
		MyTable table = (MyTable) clazz.getAnnotation(MyTable.class);
		System.out.println(table.value());
		
		// 获得类的属性的注解
		System.out.println("\n---------获得类的属性的注解---------");
		Field f = clazz.getDeclaredField("studentName");
		MyField field = f.getAnnotation(MyField.class);
		System.out.println(field.columnName() + "--" + field.type() + "---" + field.len());
		} catch (Exception e) {
     
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

注解、反射机制_第3张图片

你可能感兴趣的:(JAVA,java,反射)