JDK8新特性
可变参数
//可变参数和其他类型参数的传参
public static void method2(String str,int ... num){
//[I@4554617c
System.out.println(num);
for (int i : num) {
System.out.println(i);
}
System.out.println(str);
}
增强for循环
增强for循环和普通for循环的区别
整体来说:
增强型for循环使用起来比较方便,代码也比较简单,如果只是操作集合中元素的而不使用索引的话,建议用此方法。
对于普通for循环,如果需要使用索引进行其它操作的话,建议用这个。
区别:
增强for循环必须有被遍历的目标(如集合或数组)。
普通for循环遍历数组的时候需要索引。
增强for循环不能获取下标,所以遍历数组时最好使用普通for循环。
特点:
书写简洁。
对集合进行遍历,只能获取集合元素,不能对集合进行操作,类似迭代器的简写形式,但是迭代器可以对元素进行remove操作(ListIterator可以进行增删改查的操作)。
格式:
for(数据类型 变量名 : 被遍历的集合(collection)或者数组) {
执行语句
}
//增强for循环
public static void method3(int ...num){
//在增强for循环中数据的类型必须是集合或者数组中元素的数据类型。
for (int i : num) {
System.out.println(i);
}
}
Lambda表达式和函数式接口
Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中)
包含三部分:
1、一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数
2、一个箭头符号:->
3、方法体,可以是表达式和代码块
lambda表达式的优缺点
1、极大的简化代码。去除了很多无用的Java代码,使得代码更为简洁明了。
2、比匿名内部类更加高效
3、可读性差。在代码简洁的情况下,另一方面又让大多程序员很难读懂
lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值
集合Stream
新的 java.util.stream包中的类提供了一个 Stream API,支持对元素流进行函数式操作。
Stream API 集成在 Collections API 中,可以对集合进行批量操作,例如顺序或并行的 map-reduce 转换。
针对存在键冲突的 HashMap 的性能改进
什么是Stream
Stream(流)是一个来自数据源的元素队列并支持聚合操作
- 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
- 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
- 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
- Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
- 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
public static void methon2(){
ArrayList<String> list = new ArrayList<>();
list.add("String");
list.add("Java");
list.add("Paion");
list.add("Mat");
list.add("Mat");
list.add("World");
list.add("so");
list.add("score");
//stream 流
Stream<String> stringStream = list.parallelStream();
//计算流中元素的个数
//System.out.println(stringStream.count());
//lambda 表达式结合集合流
//从容器中获取最大值
//System.out.println(stringStream.max((a,b)->{return a.compareTo(b);}).get());
//System.out.println(stringStream.min((a,b)->{return a.compareTo(b);}).get());
System.out.println(list.parallelStream().count());
System.out.println(list.parallelStream().max((a ,b)->a.compareTo(b)).get());
System.out.println("---------");
//过滤集合中以s开头的元素
Object[] s = list.stream()
//过滤值不为空
.filter(num -> num != null)
//过滤值以s开头
.filter(str -> str.startsWith("s"))
//转换为数组
.toArray();
for (Object o:s){
System.out.println(o);
}
}
public static void methon3(){
ArrayList<Integer> list = new ArrayList<>();
list.add(23);
list.add(12);
list.add(5);
list.add(23);
list.add(53);
list.add(14);
list.add(52);
list.add(11);
Stream<Integer> stream = list.stream();
//过滤
long count = stream.filter(num->num!=null)
.filter(num->num<50).count();
System.out.println(count);
}
字符串格式化
System.out.printf("Line %s",123);
--------输出结果是-----------
Line 123
类加载机制
-
先编译,后运行,编译后的文件是一个.class二进制字节码文件
-
JVM加载我们的类去运行
类的加载
- 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化
- 加载:就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象
- 连接:
- 验证 是否有正确的内部结构,并和其他类协调一致
- 准备 负责为类的静态成员分配内存,并设置默认初始化值
- 解析 将类的二进制数据中的符号引用替换为直接引用
- 初始化 初始化就是把变量赋为默认值,把控件设为默认状态,把没准备的准备好
- 加载时机
- 创建类的实例
- 访问类的静态变量,或者为静态变量赋值
- 调用类的静态方法
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类。
类加载器
-
类加载器的概述:负责将.class文件加载到内存中,并为之生成对应的Class对象。虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行
-
类加载器的分类:
-
Bootstrap ClassLoader 根类加载器
-
Extension ClassLoader 扩展类加载器
-
Sysetm ClassLoader 系统类加载器
-
类加载器的作用:
* Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
* Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
* Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。
反射
反射获取class对象(三种方式)
Class<T> 类的概述:
1.Class 类的实例表示正在运行的 Java 应用程序中的类和接口。
2.Class 没有公共构造方法。
3.Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
反射概述
* 1.JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
* 2.对于任意一个对象,都能够调用它的任意一个方法和属性;
* 3.这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
* 4.要想解剖一个类,必须先要获取到该类的字节码文件对象。
* 5.而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
三种方式:
1:Object类的getClass()方法,判断两个对象是否是同一个字节码文件
Person p = new Person(); //创建一个对象
Class clazz2 = p.getClass(); //调用这个对象中的getClass()方法(继承于Object类),返回类型是Class
2:静态属性class,锁对象
Class clazz = Person.class; //类名.调用,返回类型是Class
3:Class类中静态方法forName(),读取配置文件
Class clazz = Class.forName("xxx.properties");
配置文件的创建,后缀名是.properties,在整个项目中创建配置文件。
反射技术获取字段
public static void method() throws Exception{
//反射技术
//获取类的Class对象
Class classz = Class.forName("com.hdrj.reflect.student");
System.out.println(classz.getName());
System.out.println("------------");
//获取所有的字段 公共字段
Field[] fields = classz.getFields();
for (Field field : fields){
System.out.println("field--"+field);
}
System.out.println("------------");
//获取所有的字段
Field[] fields1 = classz.getDeclaredFields();
for (Field field : fields1){
System.out.println(field);
}
System.out.println("------------");
//获取单个公共字段
Field name = classz.getField("address");
System.out.println(name);
System.out.println("------------");
//实例化对象
Object o = classz.newInstance();
//设置值
name.set(o,"name");
//获取o 对象name 字段的值
System.out.println(name.get(o));
}
反射获取构造器
Constructor :
1.Constructor 提供关于类的单个构造方法的信息以及对它的访问权限
2.Constructor 允许在将实参与带有底层构造方法的形参的 newInstance() 匹配时进行扩展转换,但是如果发生收缩转换,则抛出 IllegalArgumentException
Class类 :
1.Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了。
2.不过,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数。
3.然后再调用Constructor类的newInstance(“张三”,20)方法创建对象
//获取构造器
public static void methon2() throws Exception{
Class classz = Class.forName("com.hdrj.reflect.student");
Constructor[] constructors = classz.getConstructors();
for (Constructor constructor : constructors){
//public com.hdrj.reflect.student();
//public com.hdrj.reflect.student(int,java.lang.String);
System.out.println(constructor);
}
//获取带参数的构造器
Constructor constructor = classz.getConstructor(int.class,String.class);
//使用带参数的构造器实例化对象
Object java = constructor.newInstance(12,"Java");
System.out.println("constructor===" + constructor);
System.out.println("java==="+java);
}
反射获取方法
Method getDeclaredMethod(String name, Class<?>… parameterTypes)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法Method[] getMethods()
Method getMethod(String name, Class<?>… parameterTypes)
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法Object invoke(Object obj, Object… args)
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法
//获取方法
public static void method1() throws Exception{
Class classz = Class.forName("com.hdrj.reflect.student");
//拿到的是自己和父类的方法
Method[] methods = classz.getMethods();
for(Method method : methods){
System.out.println(method);
}
System.out.println("-------------------------------");
//获取方法
Method hello = classz.getMethod("hello",null);
//方法的执行
Object o = classz.newInstance();
hello.invoke(o,null);
Method say = classz.getDeclaredMethod("sum",null);
say.invoke(o, "reflect");
Method sum = classz.getDeclaredMethod("sum",null);
//暴力访问方法
sum.setAccessible(true);
sum.invoke(o,null);
}