Java基础(二十三)——Stream流、枚举、注解、自定义注解、元注解
一、Stream流
1、概念
Stream:是一个接口,功能类似于流水线的工作,主要就是用于对数据进行过滤。流(Stream)与集合类似,但集合中保存的是数据,而Stream中保存对集合或数组数据的操作。
作用:使用Stream对数据进行过滤,简化Java代码。
特点:
- Stream 自己不会存储元素。
- Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
- Stream 操作是延迟执行的,会等到需要结果的时候才执行。
Stream,提供两类方法::延迟方法、终结方法。
延迟方法:表示是调用 Stream方法之后返回值还是,Stream对象,可以继续使用用Stream的方法。
终结方法::表示是调用 Stream方法之后返回值不是,Stream对象,不能再使用Stream的方法。
2、案例一
通过案例来理解:
3、获取 Stream 流的途径
Collection 及其子类能创建 Stream 流。Map 集合不行。
4、Stream 的方法
5、案例二
通过案例来了解用法。下面是需求:
实现代码:
二、枚举
1、概念
概念:用于表示一些固定的值的时候,就可以使用枚举来定义,枚举类中会定义一些枚举项,获取值的范围只能是枚举项。
格式:
访问修饰符 enum 枚举的名称 { 枚举项 }
2、枚举注意的地方
- 每一个枚举类都是 Enum其子类。
- 每一个枚举项是一个类。
- 每一个枚举项,使用逗号进行分割,使用分号进行结尾(结尾可以不写分号,推荐使用)。
- 获取枚举项,直接通过 枚举类.枚举项就可以获取了。
- 枚举类中可以定义成员变量。
- 枚举项中可以存在构造方法,但是构造方法必须是私有的,默认也是私有的构造。
- 枚举类中可以存在抽象方法,每一个枚举项必须实现这个抽象方法。
枚举一般配合 switch 使用
3、练习
4、枚举常用的方法
三、注解
1、解释
注释:用于对代码进行解释说明,给程序员进行查看。
注解:用于对代码进行解释说明,给jvm(计算机)识别。
2、定义
注解(Annotation):也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,
与类、接口、枚 举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前
面,用来对这些元素进行说明,注释。
3、作用分类
编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】。
代码分析:通过代码里标识的元数据对代码进行分析【使用反射】。
编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】。
4、jdk 提供的注解
1.@Override:用于检查是否是重写父类的方法。
2.@Deprecated:用于标注方法是过时的方法 过时的方法可以使用 但是不建议使用。
3.@SuppressWarnings:压制黄色线警告。value = “all” 压制所有的黄色线警告。注解可以定义在类上 也可以定义方法上 也可以定义在属性上。
a、@Override——检查是否是重写父类的方法
先定义一个抽象类,然后里面定义抽象方法:
接着看其子类:
可以看到前面的注解。
如果改下方法名:
注解就出红线了。
b、@Deprecated——标注过时的方法
过时的方法可以使用,但不建议使用:
先定义一个过时的方法:
然后看看调用时:
可以看到,调用的时候划横线。但还是能调用:
c、@SuppressWarnings——压制黄线。
如果后面填写 value = “true”,则压制所有黄线:
看最右边,很多黄线。接着压制黄线看看:
现在,则一个都没有了。
四、自定义注解
1、使用前相关概念
1.格式组成:
A.元注解
B.public @interface Deprecated {}
2.注解本质:就是一个接口(下面那行通过反编译获得)
public interface MyAnno extends java.lang.annotation.Annotation {}
3.接口中的成员:(只关注) 抽象方法 ==>属性
4.属性的返回值类型(必须有返回值,且返回值类型有限制。返回值不能是 void)
A.基本数据类型 四类八种
B.String 字符串类型
C.枚举类型
D.注解类型
E.以上类型的数组类型
5.使用注解的语法: @注解的名称
6.注意点:
A.使用的注解,必须给注解的所有的属性进行赋值,属性使用default设置默认值,可以不用进行赋值。
B.使用注解,给属性的数组进行赋值的时候,只有一个值的情况,可以省略其大括号。
C.如果注解的属性,只有一个value属性,在使用注解,进行赋值的时候,可以省略注解的名称。
2、练习自定义注解
可以看到,自定义注解能创建很多抽象方法(属性),所以这里尝试写一个自定义注解:
写一个注解,空白的:
接着定义一个注解,里面创建不同类型的属性:
接着写一个类,赋予注解:
因为注解必须有返回值,所以必须往里面填上返回值:
如果填上默认值,注解里就可以不用再赋值:
可以看到,这就是一个简单的自定义注解了。
五、元注解
1、元注解相关知识
1.元注解:用于描述注解的注解就是元注解。
2.元注解四个
@Target:主要用于来表示注解作用的位置
TYPE——作用域在类上
FIELD——作用域在属性上
METHOD——作用域在方法上
@Retention:主要用于注解是否可以被识别
RetentionPolicy.RUNTIME,程序在运行期间,生成Class字节码文件,定义注解会被jvm来识别。
@Documented:用于标注是否在api文档上显示这个注解。
@Inherited:用于表示注解是否继续被子类继承的使用。
2、案例一 ——使用注解与反射调用一个类的任意的方法
先定义注解:
可以看到,这个虽然是自定义注解,但是自定义注解上面还有元注解。
定义一个类,里面一个方法:
接着,就是主要代码:
@an1(className = "com.qf.cmf.An_lx3.Student",methodName = "method1") // 在注解中填写包名类名。再注解中填写方法名
public class Demo1 {
public static void main(String[] args) {
Class demo1class = Demo1.class; // 获取当前这个类的类
an1 an = (an1) demo1class.getAnnotation(an1.class); // 取当前这个类的注解
an.className(); // 取出注解中的值(类名)
an.methodName(); // 取出注解中的值(方法名)
Class cls = Class.forName(an.className()); // 通过注解中的值反射获取 Student 类
Constructor con = cls.getConstructor(); // 通过反射获取构造方法
Object obj = con.newInstance(); // 实例化
Method mt = cls.getMethod("method1"); // 通过类取出方法
mt.invoke(obj); // 然后调用此方法
}
}
3、案例二 ——使用注解实现一个测试工具类
分析:
先来看这个注解:
接着看这个工具类:
最后来看主要代码:
public class Demo1 {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("error.txt")); // 为后续写异常到文件里做准备
int count = 0; // 累计异常的个数
TestUtils testUtils = new TestUtils(); // 先实例化工具类
Class cla = testUtils.getClass(); // 通过对象反射获取类
Method[] methods = cla.getMethods(); // 获取这个类的所有方法
if (methods != null && methods.length>0){ // 数组非空验证
for (Method m:methods) {
if (m.isAnnotationPresent(an4.class)){ // 判断方法是否有 an4 这个注解。如果有就为 true。
try {
m.invoke(testUtils); // 调用方法
}catch (Exception e){
bw.write("----开始收集异常-------");
bw.newLine();
bw.write("异常的名称:"+e.getCause().getClass().getSimpleName());
bw.newLine();
bw.write("异常的信息:"+e.getCause().getMessage());
bw.newLine();
bw.write("======异常收集完毕=======");
bw.newLine();
bw.newLine();
count++;
}
}
}
try {
bw.write("共有"+count+"个异常");
}finally {
if (bw != null){ // 关流
bw.close();
}
}
}
}
}