反射&注解总结

目录

    • 反射
      • 概念
      • 应用场景
      • 反射常用API
      • 获取字节码对象的三种方式
      • 通过字节码对象获取其他对象
      • 获取类中方法的几种方式
      • 反射普通方法调用
      • 反射私有方法调用
      • 反射私有构造方法调用
      • Field用法
      • 总结
    • 注解
      • 注解引入
      • 系统内置注解
      • 元注解
      • 自定义注解
      • 自定义注解的属性类型
      • 使用注解
      • 注解功能拓展

反射

概念

反射:java提供的一种机制,可以在类的运行时期动态的获取类中所有的信息(任意字段、构造方法,普通成员方法。。。。)

应用场景

缺点:会破坏封装性,损失性能。 尽量少用反射

安卓应用场景:安卓中一些私有的类通常是系统相关的比如调用系统硬件设备等类,设备管理器。开发需要,就只能通过反射去调用这些私有的方法

Java应用场景:解耦的。在开发中,做一个项目是很多人一起开发,a(用户登录注册相关) b(列表,加入购物车) c(订单结算) 三个程序员共同开发

反射常用API

1.java.lang.Class
2.java.lang.reflect.Constructor
3.java.lang.reflect.Method
4.java.lang.reflect.Field

获取字节码对象的三种方式

        //获取字节码对象的第一种方式:    类名.class*/
		Class clazz = User.class;
		//获取字节码对象的第二种方式:    Class.forName();   解耦合了  jdbc
	    Class clazz1 = Class.forName("cn.itsource.reflect.User");
		//获取字节码对象的第三种方式      对象.getClass()		 
		Class clazz2 = new User().getClass();

通过字节码对象获取其他对象

		//用字节码对象调用相关方法获取Field,Constructor,Method所有对象。(加s代表所有)
        Class clazz = User.class;
		Method[] ms = clazz.getMethods();
		Field[] fs = clazz.getFields();
		Constructor[] cs = clazz.getConstructors();

获取类中方法的几种方式

		Class clazz = User.class;
		Method[] ms = clazz.getMethods();    		//获取本类公有的方法和父类继承过来的方法
        Method[] ms2 = c2.getDeclaredMethods();   	//获取本类公有和私有的所有方法	
		//获取指定的方法   (不加s代表指定)(没有参数类型就不写)
        Method m = clazz.getMethod("method",int.class);  		//获取本类和父类指定公有方法
		Method m2 = clazz.getDeclaredMethod("method",int.class);//获取本类指定可以是私有方法

反射普通方法调用

		Class<User> clazz = User.class;
		//获取指定的方法,("方法名",参数类型.class)
		Method m = clazz.getMethod("method",int.class);
		User user = new User();
		//返回值表示调用方法本身的返回内容
		// obj :表示方法所属的对象 ,args:表示方法的实际参数。
		Object r = m.invoke(user, 10);
		System.out.println(r);

反射私有方法调用

private编译时期有效,反射是在运行时期

		Class clazz = User.class;
		Method m = clazz.getDeclaredMethod("methodPrivate");		//2.获取指定的方法
		m.setAccessible(true);										//暴力反射。破坏了封装,设置可以访问。
		//通过反射获取类的对象。但是private构造创建对象无效。需要先用反射去暴力获取私有构造方法再造对象
		Object newInstance = clazz.newInstance();	//底层反射。或者还用User user = new User();
		m.invoke(newInstance);

反射私有构造方法调用

		//获取Runtime构造器对象
		Constructor<Runtime> c = Runtime.class.getDeclaredConstructor();
		//设置可以访问
		c.setAccessible(true);
		//invoke --> newInstance 通过反射创建Runtime类对象
		Runtime newInstance = c.newInstance();
		System.out.println(newInstance);

		//通过单例模式创建对象
		Runtime runtime = Runtime.getRuntime();
		System.out.println(newInstance);

Field用法

		Field f = User.class.getDeclaredField("name");
		//设置可以访问
		f.setAccessible(true);
		User user = new User();
		f.set(user, "jack");
		System.out.println(f.get(user));
		System.out.println(user.getName());

总结

1.找到字节码对象
2.通过字节码对象找到具体对象(Method,Constructor,File)。
3.找具体要反射的方法
4.要反射的方法是私有的需要设置可以访问,setAccessible
5.调用,invoke,newInstance,set

注解

注解引入

使用注解语法:@注解名字
注解(annotation):用来标记代码的,简单理解就是一种标记,给代码看的.
注释:给程序员看的,用来说明解释代码.
作用:1.可以用来检验是否符合规定。2.使代码看起来简洁.清晰

系统内置注解

@Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return super.toString();
	}

@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
有了这个标记的方法,表示该方法已经过时,但是还可以调用,不推荐使用它,因为有了新的方法去替代它。
jdk更新换代,会替换到以前过时的一些功能,升级了,旧的也不会删掉

	@Deprecated
	public static void test(){}

@SuppressWarnings - 指示编译器去忽略注解中声明的警告。

    //抑制黄色波浪线的警告.
    @SuppressWarnings({ "rawtypes", "unused" })
    ArrayList arrayList = new ArrayList();

从 Java 7 开始,额外添加了 3 个注解:
@SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
@FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次

元注解

元注解:在自定义注解的时候,用来标记注解的注解。

@Documented 如果使用的注解中包含这个元注解,那么我们在生成文档api的时候,会有这个注解的描述
@Target 表示标记自定义注解可以用在什么地方
@Retention 标记自定义注解的生命周期 source class runtime
@Inherited 标记注解可以被继承.

自定义注解

/**
 * @author Administrator
 * @see 参考xxxx
 * @since 从jdk1.8
 * @version 1.0
 */
@Documented
public @interface 注解名字{
    
}

自定义注解的属性类型

/**
 * @author Administrator
 *自定义注解语法:
 * public @interface 注解名字{
 *    类型 属性名();
 *    //类型:8种,String,数组,枚举,其他注解类型.
 *    类型 属性名() default 值;
 * }
 */
@Documented
@Target(value={ElementType.TYPE,ElementType.PARAMETER})
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    int a() ;
	String b() ;
	int[] c() ;
	TT  d();
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {

    ElementType[] value();
}
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**Type parameter declaration */
    TYPE_PARAMETER,

    /**Use of a type */
    TYPE_USE
}

使用注解

@Documented
@Target(value={ElementType.TYPE,ElementType.PARAMETER})
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
	int a() default 1;
	String b() default "abc";
	String[] value() ;
//	TT  d();
}

1.如果一个注解中只有一个属性需要赋值,属性名字叫value,那么可以省略value,直接给对应类型的值.
2.如果属性是一个数组,赋值的时候,只有一个值,可以省略花括号{}

@MyAnnotation(value={"发发发"},a=2)
public class MyAnnotationTest2 {
	@TT
	public static void test(){
		System.out.println("test......");
	}
}

注解功能拓展

1.找到类的字节码对象
2.找到有哪些方法
3.通过方法对象找到哪个方法上有注解
4.执行某方法

public class DemoTT {

	public static void main(String[] args) throws Exception {
		//获取类上的注解
	/*	Annotation[] as = MyAnnotationTest2.class.getAnnotations();
		for (Annotation annotation : as) {
			System.out.println(annotation);
		}														*/
        
		System.out.println("-------------");
		//获取指定类的所有方法.
		Method[] ms = MyAnnotationTest2.class.getDeclaredMethods();
		for (Method m : ms) {
			//获取方法上面的TT注解对象
			TT tt = m.getAnnotation(TT.class);
			//判断有TT注解对象的方法
			if (tt instanceof TT) {
				//调用有TT注解对象的方法.
				m.invoke(new MyAnnotationTest2());
			}
		}
	}
}
@MyAnnotation(value={"发发发"},a=1)
public class MyAnnotationTest2 {
	@TT
	public static void test(){
		System.out.println("test......");
	}
	@TT
	public static void test2(){
		System.out.println("test2......");
	}
	public static void test3(){
		System.out.println("test3......");
	}
}

你可能感兴趣的:(笔记总结,java,反射)