1.StreamAPI
好处:直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤流、打印
1.1 Stream流的常见生成方式
Stream流的使用的步骤:
1 生成流:
? 通过数据源(集合,数组)生成流 集合名(数组名).stream
static <T> Stream<T> | stream(T[] array) 返回顺序[Stream ]与指定的数组作为源。 |
---|
default Stream<E> | stream() 返回以此集合作为源的顺序 Stream 。 | static <T> Stream<T> | of(T... values) 返回其元素是指定值的顺序排序流。 | static <T> Stream<T> | of(T t) 返回包含单个元素的顺序 Stream 。 |
2 中间操作
? 一个流的后面可以跟随零个或多个中间操作,目的只要是打开流,对其中数据进行过滤/映射,然后返回一个新的流。交给下一个操作使用
Stream<T> | filter(Predicate<? super T> predicate) 返回由与此给定谓词匹配的此流的元素组成的流。 |
---|
Stream<T> | limit(long maxSize) 返回由此流的元素组成的流,截短长度不能超过 maxSize 。 | Stream<T> | skip(long n) 在丢弃流的第一个 n 元素后,返回由该流的 n 元素组成的流。 | Stream<T> | sorted() 返回由此流的元素组成的流,根据自然顺序排序。 | Stream<T> | sorted(Comparator<? super T> comparator) 返回由该流的元素组成的流,根据提供的 Comparator 进行排序。 | Stream<T> | peek(Consumer<? super T> action) 返回由该流的元素组成的流,另外在从生成的流中消耗元素时对每个元素执行提供的操作。 | <R> Stream<R> | map(Function<? super T,? extends R> mapper) 返回由给定函数应用于此流的元素的结果组成的流。 | DoubleStream | mapToDouble(ToDoubleFunction<? super T> mapper) 返回一个 DoubleStream ,其中包含将给定函数应用于此流的元素的结果。 | IntStream | mapToInt(ToIntFunction<? super T> mapper) 返回一个 IntStream ,其中包含将给定函数应用于此流的元素的结果。 | LongStream | mapToLong(ToLongFunction<? super T> mapper) 返回一个 LongStream ,其中包含将给定函数应用于此流的元素的结果。 | static <T> Stream<T> | concat(Stream<? extends T> a, Stream<? extends T> b) 创建一个懒惰连接的流,其元素是第一个流的所有元素,后跟第二个流的所有元素。 | Stream<T> | distinct() 返回由该流的不同元素(根据 [Object.equals(Object) ])组成的流。 |
3 终止操作
? 一个流只能有一个终结操作,当这个流执行了终结操作时,此时流就会被关闭。无法进行后续操作。
long | count() 返回此流中的元素数。 |
---|
void | forEach(Consumer<? super T> action) 对此流的每个元素执行操作。 |
2 类的加载和反射
2.1 类加载(记忆)
当某一个程序在运行时,需要使用某一个类,如果该类还未被加载到内存中,则系统会通过类的加载,类的链接,类的初始化三个步骤来完成对类的初始化。
类的加载:
- ? 就是指将class文件读入内存,并位置创建一个java.lang.Class对象。
- ? 任何类被使用时,系统都会为之建立一个java.lang.Class对象。
类的链接:
- ? 验证阶段:用户检验被加载的类是否有完整的结构,并和其他的类协调一致。
- ? 准备阶段: 负责为类的变量分配内存,并设置默认初始值
- ? 解析阶段: 将类的二进制数据中的符号引用替换为直接引用
类的初始化:
作用:
? 主要就是对类的变量进行初始化
步骤:
- ? 假如类还未被加载和链接,则程序先加载并链接该类
- ? 假如该类的直接父类还未被加载,则先初始化其直接父类
- ? 假如类中具有初始化语句,则系统将一次执行这些初始化语句
注意:在自行第二个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤1–3
类的初始化时机:
- ? 创建类的实例;
- ? 调用类的类方法
- ? 访问类或者接口的类变量或者为该类变量赋值
- ? 使用反射方式来强制创建某个类或者接口对应的Class对象
- ? 初始化某个类的子类
- ? 直接使用java命令来运行某个主类
2.2 类加载器
作用:
? 负责将class文件加载到内存中,并为之生成对应的Class,虽然我们不用过分的关心类的加载机制,但是了解这个机制就能更好的理解程序的运行
jvm的类加载机制:
? 全盘负责: 就是当一个类加载器负责加载某个Class的时候,该Class所以来的和引用的其他的Class也将有该类加载器负责载入,除非显式的使用另外一个类加载器来载入
? 父类委托:就是当一个类加载器负责加载某个Class时,先让父类加载器试图加载,只有在父类加载器无法加载该类时,才尝试从自己的类路径中加载该类
? 缓存机制:保证所有的加载过得Class在再次使用时,都并不会被重新加载,所有加载过得Class都会被缓存。当需要某个Class对象的时候,类加载器先从缓存区中搜索,只有当缓存区不存在时,系统采用读取该类对应的二进制数据,并将其转换为Class对象,存储到缓存区。
2.3 java中的内置类加载器
Bootstrap class Load: 这是jvm的内置类加载器 通常表示为null,并且没有父类
Paltform class load: 平台类加载器 可以看到所有的平台,包括平台类加载器或其祖先定义的JAVASE平台的API
System class load 应用程序类加载器 与平台类加载器不同,系统类加载器加载通常用于定义应用程序类路径和模块路径和jdk特定工具类
类加载器的继承关系:
? System的父加载器为Platform 而platform的父加载器为Bootstrap
ClassLoad类表示类加载器:
?
static ClassLoader | getSystemClassLoader() 返回用于委派的系统类加载器。 |
---|
ClassLoader | getParent() 返回父类加载器进行委派。 |
3 反射
反射指的就是在运行时获取一个类的变量和方法信息,然后通过获取到的信息来创建对象,调用方法的一种机制。
由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。
3.1 获取Class对象的方式
public static void main(String[] args) throws ClassNotFoundException {
Class<Student> c1 = Student.class;
System.out.println(c1);
Class<Student> c2 = Student.class;
System.out.println(c1 == c2);
System.out.println("------------------------");
Student stu = new Student();
Class<? extends Student> c3 = stu.getClass();
System.out.println(c1 == c3);
System.out.println("------------------------");
Class<?> c4 = Class.forName("cn.lanqiao.clazz.Student");
System.out.println(c1 == c4);
}
3.2 反射获取类的构造方法
Constructor<T> | getConstructor(类<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映 Constructor 对象表示的类的指定的公共 类 函数。 |
---|
Constructor<?>[] | getConstructors() 返回包含一个数组 Constructor 对象反射由此表示的类的所有公共构造 类 对象。 | Constructor<T> | getDeclaredConstructor(类<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映 Constructor 对象表示的类或接口的指定 类 函数。 | Constructor<?>[] | getDeclaredConstructors() 返回一个反映 Constructor 对象表示的类声明的所有 Constructor 对象的数组 类 。 |
Constructor类用于创建对象方法
T | newInstance(Object... initargs) 使用此 Constructor 对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。 |
---|
3.3 反射获取成员变量
Field | getField(String name) 返回一个 Field 对象,它反映此表示的类或接口的指定公共成员字段 类 对象。 |
---|
Field[] | getFields() 返回包含一个数组 Field 对象反射由此表示的类或接口的所有可访问的公共字段 类 对象。 | Field | getDeclaredField(String name) 返回一个 Field 对象,它反映此表示的类或接口的指定已声明字段 类 对象。 | Field[] | getDeclaredFields() 返回的数组 Field 对象反映此表示的类或接口声明的所有字段 类 对象。 |
3.4 成员方法
Method | getMethod(String name, 类<?>... parameterTypes) 返回一个 方法 对象,它反映此表示的类或接口的指定公共成员方法 类 对象。 |
---|
Method[] | getMethods() 返回包含一个数组 方法 对象反射由此表示的类或接口的所有公共方法 类 对象,包括那些由类或接口和那些从超类和超接口继承的声明。 | Method | getDeclaredMethod(String name, 类<?>... parameterTypes) 返回一个 方法 对象,它反映此表示的类或接口的指定声明的方法 类 对象。 | Method[] | getDeclaredMethods() 返回包含一个数组 方法 对象反射的类或接口的所有声明的方法,通过此表示 类 对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。 |
3.5 反射的应用
3.5.1 反射对于泛型的检查
@Test
public void reflectTest01() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(20);
Class<? extends List> c = list.getClass();
Method addMethod = c.getMethod("add",Object.class);
addMethod.invoke(list,"aaaa");
addMethod.invoke(list,true);
System.out.println(list);
}
3.5.2 运行配置文件中指定类和方法
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Properties prop = new Properties();
FileReader fr = new FileReader("day_16/resources/myClass.properties");
prop.load(fr);
fr.close();
String className = (String) prop.get("className");
System.out.println(className);
String methodName = (String) prop.get("methodName");
System.out.println(methodName);
Class<?> c = Class.forName(className);
Constructor<?> constructor = c.getConstructor();
Object obj = constructor.newInstance();
Method method = c.getMethod(methodName);
method.invoke(obj);
}
|