笔记1-2:java反射、函数式编程、注解

反射笔记

java三阶段:1-源码 2-class 3-runtime

一. 获取Class对象的方式

---【获取Class.forName("全类名")】:将自己吗文件加载进内存,返回Class对象
      多用于配置文件,将类名定义在配置文件中,读取文件,加载类
---【类名.class】:通过类名的属性class获取
      多用于参数传递
---【对象.getClass()】:getClass()方法在 Object类中定义着
      多用于对象的获取字节码的方式
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个

二. Class对象功能

1. 暴力反射    Field/Constructor/Method对象.setAccessible(true)==忽略访问权限修饰符的安全检查
2.【获取成员变量/们】
      Field[] 	getFields()                      获取所有public修饰的成员变量
      Field 	getField(String name)            获取指定名称的public修饰的成员变量
      Field[] 	getDeclaredFields()              获取所有的成员变量,不考虑修饰符
      Field 	getDeclaredField(String name)    获取指定名称的,不考虑修饰符
      [操作]
            设置值		void 		set(Object obj, Object value)  
            获取值		Object值 	get(Object obj) 
		
3.【获取构造方法/们】
      Constructor<?>[] getConstructors()  
      Constructor<T> 	getConstructor(类<?>... parameterTypes)  
      Constructor<T> 	getDeclaredConstructor(类<?>... parameterTypes)  
      Constructor<?>[] getDeclaredConstructors()  
      [操作]
            创建对象      T表示返回对象类型
            T    Construct对象.newInstance(Object... initargs)  
            T    Class对象.newInstance()(空参数构造方法创建对象可这样简化)
		
4.【获取成员方法/们】
      Method[] getMethods()  
      Method     getMethod(String name, 类<?>... parameterTypes)  
            name==方法名称	parameterTypes==参数类型列表
      Method[]    getDeclaredMethods()  	
      Method     getDeclaredMethod(String name, 类<?>... parameterTypes)  
      [操作]
            执行方法	       Object invoke(Object obj, Object... args)  
                  参数:obj==方法类的对象    args==方法参数列表
            获取方法名称    String getName()
		
5.【获取全类名】
      String getName()  

函数式编程

函数式编程:

  通过匿名内部类和lambda表达式完成*

匿名内部类:

  定义一个接口,该接口定义一个未实现的方法,当其他类方法参数用到该接口类型时,可以直接new该接口并实现方法即可。

Lambda表达式:

当某个方法需要一个参数,这个参数类可以是一个接口并且接口只有一个方法时可用Lambda
    1-一些参数
    2-一个箭头
    3-一段代码
    格式:(参数列表)->{一些重写方法的代码};
    可省略内容:
          1-括号中参数列表的数据类型,可省略
          2-括号中的参数如果只有一个,那么类型和括号都可以省略
          3-如果{}中代码只有一行,无论是否有返回值,都可以省略({},return,分号)
                注意:要省略{},return,分号必须一起省略
    两者实现都是:定义一个接口,接口只定义一个方法,
          直接创建接口并重写方法作为参数传入需要相应类型参数的方法中
          匿名内部类需要重写方法和方法体,
    区别:Lambda表达式更加简洁一些,
	在Lambda表达式中不需重写方法,

Lambda引用

可以简化lambda表达式来简化代码
      使用前提是对象名是已经存在的,成员方法也存在
执行过程
      创建函数式接口-->lambda实现接口方法-->普通方法调用接口方法


【方法引用】
            @FunctionalInterface //函数式接口
            interface Printabe{
                  public void print(String str);
            }
            //普通方法
            public static void printString(Printabe p) {
                  p.print("helloword");
                  //这里p调用的print("helloword")即等于调用了arg->System.out.println(arg)
                  //"helloword"赋值给参数arg,方法体System.out.println(arg)打印了arg(即helloword)出来
            }
            //-----lambda实现
            printString(p->System.out.println(arg));
            p即print()方法的参数str,
                  System.out.println(arg)即相当于该方法的方法体
            //-----引用实现
            printString(System.out::println);

【定义类对象引用方法】
	//-----Lambda表达式实现
	printString((s)->{
		//创建对象
		t05_1MethodRerObj_方法引用 obj = new t05_1MethodRerObj_方法引用();
		obj.printUpperCaseString(s);
	}); 
	//-----引用实现
	t05_1MethodRerObj_方法引用 obj = new t05_1MethodRerObj_方法引用();
	printString(obj::printUpperCaseString);

【类名引用静态方法】
            //函数式编程所需接口
	@FunctionalInterface
	interface Calcable{
		public int calsABs(int number);
	}
	//使用方法
	public static int method(int number,Calcable c) {
		return c.calsABs(number);
	}
	//-----Lambda表达式实现
	int numberabs = method(-10, (n)->{
		return Math.abs(n);
	});
	//-----引用实现
	int numberabs2 = method(-10, Math::abs);
	
【super引用父类方法】
	super::父类方法名
	
【this引用本类方法】
	this::本类方法名
	
【类引用构造方法】
	//定义一个方法,参数传w递姓名和PsesonBuilder接口,方法中通过姓名创建Person对象
	public static void printName(String name,PersonBuilder pb) {
		Person person = pb.builPerson(name);
		System.out.println(person);
	}
	//-----lambda表达式实现
	//调用printName,传递Lambda表达式
	printName("迪丽热巴", (String name)->{
		return new Person(name);
	});
	//-----引用实现
	//创建对象已知,new
	printName("古力娜扎", Person::new);//使用Person类的带参构造方法,通过传递的姓名创建对象

	例子2:创建数组------------------------------------------------
	
	@FunctionalInterface//函数式编程所需接口
	interface AarryBuilder{
		//定义一个创建int类型数组的方法,参数传递数组场地,返回创建好的int类型数组
		int[] builderAray(int length);
	}
	//创建方法
	public static int[] CreateArray(int length,AarryBuilder ab) {
		return ab.builderAray(length);//该语句相当于使用了lambda表达式内分方法体
	}
	//------lambda表达式
	CreateArray(10, (len)->{//第二参数相当于实现接口方法便于创建方法调用该方法
		return new int[len];
	});
	//-----引用实现
	//int[]引用new 根据参数传递的长度来创建数组
	CreateArray(10,int[]::new);

注解

命令:javadoc--生成文档 javap--反编译

  • jdk1.5后新特性
  • 说明程序的
  • 定义注解--@interface 使用注解--@注解名称

注解本质就是一个接口,默认继承annotation接口

  • jdk预定义注解

    • @Override :检测被该注解标注的方法是否继承自父类(接口)
    • @Deprecated :表示该注解标注的内容已过时
    • @SuppressWarnings :压制警告
  • 自定义注解 属性:接口中的抽象方法 其返回值类型有如下:

    • 基本数据类型
    • String
    • 枚举
    • 注解
    • 以上类型数组

定义属性 使用default关键字给属性赋初始值 使用注解时有默认值的属性可不赋值
使用注解时 只赋值一个属性且属性名叫value则value可省略
数组赋值 值用{}包裹,单个值{}可省

  • 元注解:描述注解的注解
    • @Target 描述注解能够作用位置
      • ElementType.TYPE 表示只能作用到类上
      • ElementType.METHOD 可以作用到方法上
      • ElementType.FIELD可以作用到成员变量上
    • @Retention 描述注解被保留的阶段
      • RetentionPolicy.RUNTIME 被描述的注解会保留到class字节码文件中被jvm读取到
    • @Documented 描述注解是否被抽取到api文档中
    • @Inherited 描述注解是否被子类继承

解析注解 获取属性中定义的属性值

  • 获取加了注解的类字节码class文件对象 即.class等
  • 获取注解对象 ----字节码文件对象.getAnnotation(注解字节码 即注解名.class) 其实就是在内存中生成了一个该注解接口的子类实现对象
  • 调用注解对象中定义的抽象方法(即注解的属性)获取属性值

posted @ 2020-07-19 21:36  小艾影  阅读(249)  评论(0编辑  收藏  举报