Java新特性学习

Java8新特性

Lambda表达式

首先介绍匿名内部类:必须是类或者接口,其中只有一个抽象方法。
    new 类名(接口名)(){
        重写抽象方法
    }
    //第一种方式
    new Animal(){
        public void eat(){
            System.out.println("吃肉");
        }
    }.eat(); //整个是相当于是抽象类的子类对象,然后可以调用eat方法
    //第二种方式
    Animal A=new Animal(){ //相当于多态 父类引用指向子类对象
        public void eat(){
            System.out.println("吃肉");
        }
    }
    a.eat();
Lambda表达式:
    基础语法:箭头操作符或者叫Lambda操作符(->),将Lambda表达式拆分成两部分,左侧对应的是表达式的参数列表,右侧是表达式中所执行的功能(Lambda体)。Lambda左侧的参数列表就是对应接口中抽象方法的参数列表,右侧对应抽象方法的实现逻辑。
    语法格式:
    1、无参数、无返回值:()->System.out.println("你好");比如Runnable:
        Runnable r=()-> System.out.println("hello world");
    2、有一个参数,并且无返回值:举例:(若只有一个参数,那么参数的小括号可以省略不写)
        public interface Consumer<T> {
            void accept(T t);
        }
        Consumer<String> c=(x)-> System.out.println(x);
        //Consumer<String> c= x-> System.out.println(x);
        c.accept("hhahaha");
    3、有两个参数或者多个参数,并且Lambda体中有多条语句(Lambda体必须使用大括号),有返回值。
         Comparator<Integer> c=(x, y)->{
            System.out.println("函数式接口");
            return Integer.compare(x,y);
        };
        System.out.println(c.compare(5,3));
    4、如果有两个参数并且有返回值,Lambda体中只有一条返回值,return和大括号都可以省略不写。
        Comparator<Integer> c=(x, y)->Integer.compare(x,y);
        System.out.println(c.compare(5,3));
    5、Lambda表达式的参数列表数据的数据类型可以省略不写。
Lambda表达式需要函数式接口的支持,接口中只有一个抽象方法的接口,可以使用一个注解使用@FunctionalInterface修饰一下,可以检查是不是函数式接口。

四大内置核心函数式接口

方法引用和构造器引用

方法引用:如果在Lambda中的内容有方法已经实现了,可以使用方法引用。
    固定的格式:
        对象::实例方法名;要求是抽象体中的方法中的参数列表和返回值类型和Lambda体中的参数列表和返回值类型是一样的。
            PrintStream ps=System.out;
            Consumer<String> con=ps::println;
            Consumer<String> con=System.out::println;
        类::静态方法名;
            Comparator接口中有一个抽象方法compare(), int compare(T o1, T o2);和Lambda表达式中的(实现类中)方法的参数列表和返回值类型是一致的:
            public final class Integer extends Number implements Comparable<Integer> {
                public static int compare(int x, int y) {
                    return (x < y) ? -1 : ((x == y) ? 0 : 1);
                }
                ....
            }
            ---------------------------------------------
            举例:
            Comparator<Integer> com=(x,y)->Integer.compare(x,y);
            Comparator<Integer> com1=Integer::compare;
        类::实例方法名
            如果说在Lambda中第一个参数是方法的调用者,第二个参数是被调用方法的参数时,可以使用类:实例方法名。x.equals(y).
构造器引用:类名::new;==(new Person()),自动匹配符合的构造器。
数组引用:type[]::new; (String[]::new;)

Stream流

介绍:在util包中
    Stream是处理集合的关键抽象概念,他可以指定你希望对集合处理的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用StreamAPI堆积和数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用StreamAPI类执行并行操作。
    流是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。集合讲的是数据、流讲的是计算。Stream自己不会存储元素。Stream不会改变源对象,相反他们会返回一个持有结果的新Stream。Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
操作步骤:
创建Stream:有四种形式
    1、可以通过collection系列集合提供的stream()或者parallelStream()
        List<String> list=new ArrayList<>();
        Stream<String> stream = list.stream();
    2、通过Arrays中的静态方法获取数组流
        String[] str=new String[10];
        Stream<String> stream1 = Arrays.stream(str);
    3、通过Stream类中的静态方法of(),也可以传递数组
        Stream<String> stream3 = Stream.of("aa");
    4、创建无限流,
        迭代:第一个参数是seed种子,也就是起始值,第二个参数是操作
        Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
        生成:
        Stream<Double> stream5 = Stream.generate(() -> Math.random());
中间操作:没有任何效果,必须有终止操作
    List<Person> list=Arrays.asList(
            new Person("a",10),
            new Person("b",20),
            new Person("c",30),
            new Person("d",40),
            new Person("e",50),
            new Person("f",60)
    );
    筛选和切片:
        filter()-》接收Lambda,从流中排除某些元素
            list.stream()
                .filter((p)->p.getAge()>20)
                .forEach(System.out::println);
            }
        limit()-》截断流,使其元素不超过给定数量
            list.stream()
                .filter((p)->p.getAge()>20)
                .limit(2)
                .forEach(System.out::println);
            }
        distinct()-》筛选,通过流所生成元素的hashCode()和equals()去除重复元素
        skip()-》跳过元素,返回一个扔掉前n个元素的流。若流中元素不足n个,则返回一个空流。与limit互补。
            list.stream()
                .filter((p)->p.getAge()>20)
                .skip(2) //扔掉前两个
                .forEach(System.out::println);
    映射:
        map()-》接收Lambda,将元素转换成其他形式或者提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
            List<String> list1=Arrays.asList("aaa","bbb");
            list1.stream()
                .map((str)->str.toUpperCase())
                .forEach(System.out::println);
        flatMap()-》接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有的流连接成一个流。
    排序:
        sorted()-》自然排序(Comparable)
            List<Integer> list2=Arrays.asList(1,2,5,9,4,6,7);
            list2.stream()
                .sorted()
                .forEach(System.out::println);
        sorted(Comparator com)-》定制排序
        peek()        
终止操作(终端操作)
    查找与匹配:
        min()-》返回流中的最小值
        max()-》返回流中的最大值
        count()-》返回流中元素的总个数
        anyMatch()-》检查是否至少匹配一个元素
        allMatch()-》检查是否匹配所有元素
        noneMatch()-》检查时候没有匹配所有元素
        findFirst()-》返回第一个元素
        findAny()-》返回当前流中的任意一个元素
    规约:
        reduce()-》将流中元素反复结合起来得到一个值,把起始值作为x,然后从流中取出一个值作为y,然后以此类推。
            List<Integer> list2=Arrays.asList(1,2,5,9,4,6,7);
            list2.stream()
                .reduce(0,(x,y)->x+y);
    收集:
        collect()-》将流转换为其他形式。接收一个Collector接口的实现,用于给stream中元素做汇总的方法
            list.stream()
                .map(Person::getName)
                .collect(Collectors.toList())
                .forEach(System.out::println);
        forEach()-》
        forEachOrdered()
        toArray()

Optional类

 //不能传递null 否则出现空指针异常,在构建的时候 Optional<Person> optional=Optional.of(new Person()); Person person = optional.get(); System.out.println(person);

接口

可以有默认方法(使用default关键字修饰,该方法可以实现),其中有一个是类优先原则,如果一个接口中定义了一个默认方法,另一个父类或接口中又定义了一个同名的方法时,选择父类中的方法,如果父类中提供了具体的实现,那么接口或接口中具有相同名称和参数的默认方法就会被忽略。接口冲突,如果一个父接口提供一个默认方法,另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认的),那么必须覆盖该方法来解决冲突。
静态方法:接口中可以有静态方法

时间和日期的API

整体都在Time包下:是不可变的线程安全的。
java。time包中的是类是不可变且线程安全的。新的时间及日期API位于java.time中,下面是一些关键类
●Instant——它代表的是时间戳
    //默认获取的是UTC(世界协调时间)时区为基础的 时间戳
    Instant now = Instant.now();
    System.out.println(now);
    //进行偏移量运算,得到的为北京现在的时间
    OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(8));
    System.out.println(offsetDateTime);
    //转换成毫秒
    long l = now.toEpochMilli();
    System.out.println(l);
●LocalDate——不包含具体时间的日期,比如2014-01-14。它可以用来存储生日,周年纪念日,入职日期等。
    //今天的日期是:2021-03-16,只包含日期
    LocalDate localDate=LocalDate.now();
    System.out.println("今天的日期是:"+localDate);
    //获取年月日
    localDate.getYear();
    localDate.getMonthValue();
    localDate.getDayOfMonth();
●LocalTime——它代表的是不含日期的时间
    //获取当前时间,不包含日期  当前的时间是:16:40:34.591
    LocalTime localTime=LocalTime.now();
    System.out.println("当前的时间是:"+localTime);
●LocalDateTime——它包含了日期及时间,不过还是没有偏移信息或者说时区。
    //指定当前时间
    LocalDateTime localDateTime=LocalDateTime.of(2021,10,10,10,10,10);
    System.out.println(localDateTime);
    //在当前的基础上加减年月日等;LocalDate只能加减年月日,LocalTime只能加减时分秒
    LocalDateTime localDateTime1 = localDateTime.plusYears(1);
    System.out.println(localDateTime1);
    LocalDateTime localDateTime2 = localDateTime.minusYears(1);
    System.out.println(localDateTime2);
●Duration:计算两个时间之间的间隔
●Period:计算两个日期之间的间隔
​
时间校正器:
    TemporalAdjuster:
    dayOfWeekInMonth() – 一周中的某一天,例如,三月中第二个星期二
    firstDayOfMonth() – 当前月的第一天
    firstDayOfNextMonth() – 下一个月的第一天
    firstDayOfNextYear() – 下一年的第一天
    firstDayOfYear() – 当年的第一天
    lastDayOfMonth() – 当月的最后一天
    nextOrSame() – 下一次或当天发生的一周中的某天
​
    //指定为月中的第一天
    LocalDateTime localDateTime2 = localDateTime.with(TemporalAdjusters.firstDayOfMonth());
    System.out.println(localDateTime2);
    可以自定义指定,查文档
    
时间日期格式化:DateTimeFormatter
    DateTimeFormatter isoDateTime = DateTimeFormatter.ISO_LOCAL_DATE;
    LocalDateTime localDateTime3=LocalDateTime.now();
    String format = localDateTime3.format(isoDateTime);
    System.out.println(format);
    DateTimeFormatter.ofPattern("自定义格式");
    //将字符串解析成时间格式
    LocalDateTime parse = localDateTime3.parse("需要解析的字符串", "格式");
    
时区的处理:
    ●ZonedTime
    ●ZonedDate
    ●ZonedDateTime——这是一个包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的。

Java9新特性

模块化特性

    简单说模块是代码和数据的封装体。这里的代码指的是一些包含类型的Packages 。Packages是类路径名称,模块就是一个或者多个Package组成的封装体。
    实现目标:
        主要目的是在于减小内存的开销
        只须必要模块,而非全部jdk模块,可以简化各种类库和大型应用的开发和维护
        改进JavaSE平台,使其可以适应不同大小的计算设备
        改进其安全性,可维护性,提高性能

    如图所示,如果在ModuleTest中直接调用Person是不能调用的,因为处在不同的模块中。可以通过导入导出模块的方式进行调用。创建module-info.java文件。
    被调用的:
        module java9demo {
            //导出包
            exports com.hqm.pojo;
        }
    调用的:
        module javatest {
            //导入模块名
            requires java9demo;
        }

jShell命令

    JShell其实就是一个命令行工具,输入片段代码马上就可以看到结果,相当于脚本一行行解析执行,用户可以体验一把Java交互式编程环境。
    JShell的目标是提供一个交互工具,通过它来运行和计算java中的表达式。开发者可以轻松地与JShell交互,其中包括:编辑历史,tab键代码补全,自动添加分号,可配置的imports和definitions。其他的很多主流编程语言如python都已经提供了console,便于编写一些简单的代码用于测试。值得一提的是,JShell并不是提供了新的一个交互语言,在JShell中编写的所有代码都必须符合java语言规范;图形界面和调试支持也没有,JShell的一个目标是可以在IDE中使用JShell交互,而不是实现IDE实现的功能。
    使用jShell,可以在命令行中输入jshell,就可以进入jshell环境。

默认情况下导入的包

 

多版本兼容jar包

多版本兼容 JAR 功能能让你创建仅在特定版本的 Java 环境中运行库程序时选择使用的 class 版本。

接口的私有方法

jdk7只能定义抽象方法;jdk8可以定义默认方法和静态方法;jdk9可以定义私有方法
jdk9:
    public interface MyInterface {
        //定义默认方法
        default void method1(){
            System.out.println("接口中的私有方法");
            method2();
        }
        //定义私有方法
        private void method2(){
            System.out.println("接口中的私有方法2");
        }
    }

钻石操作符(泛型)

在Java7之前每次声明泛型变量的时必须左右两边都同时声明泛型:
    List<String> list = new ArrayList<String>();
在Java8中,对这一点进行了改进,就不必两边都要声明泛型,这种只适用<>标记的操作,称之为钻石操作符Diamond Operator:
    List<String> list = new ArrayList<>(); 类型推断
在Java9中,钻石操作符能与匿名实现类共同使用:
    List<String> list = new ArrayList<>() {
        @Override
        public int size() {
            return super.size();
        }
    };

异常处理

JDK8异常处理对象必须在try的小括号内进行初始化。
JDK9新特性:
  -try前边可以定义流对象
  -try后边的( )中可以直接引入流对象的名称(变量名),此时的对象是final的。
  -在try代码执行完毕后会自动释放资源,不用写finally
    public static void main(String[] args) throws FileNotFoundException {
            FileInputStream inputStream = new FileInputStream("d:\\a.txt");
            FileOutputStream outputStream = new FileOutputStream("d:\\d.txt");
            try (inputStream; outputStream) { //引用多个的时候可以用分号分开
                int len = 0;
                byte[] bytes = new byte[1024];
                while ((len = inputStream.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, len);
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
        }

下划线使用的限制

命名标识符的时候进行限制: 
    在java 8 中,标识符可以独立使用“_”来命名:
        String _="hello"; 这样是可以的
    在java 9 中规定“_”不再可以单独命名标识符了,如果使用,会报错:
        String _="hello"; 这样是不行的

String底层存储结构的变化

    之前存储string的结构是字符数组。jdk9中使用的存储结构是字节数组。如果是中文的话就会使用编码标识标注一下,UTF-16明确一个字符是两个字节。StringBuffer和StringBuild同样使用了字节数组。
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    @Stable
    private final byte[] value;
    ......
String:不可变的字符序列
StringBuffer:线程安全的,执行效率低,可变的字符序列
StringBuild:线程不安全的,执行效率高,可变的字符序列

创建只读集合

jdk8集合变为只读:
    List<String> s=new ArrayList<>();
    List<String> s1=Collections.unmodifiableList(s);
jdk9集合变为只读:
    List<Integer> list = List.of(1, 2, 3); //调用of方法
    //map中是entry类型的数组,map集合除了可以使用of方法,还可以使用ofEntries方法。
    Map.ofEntries(Map.entry(1,2), Map.entry(3,4));

增强的StreamAPI

//jdk9中Stream新添加的四个方法
    takeWhile::从 Stream 中获取一部分数据, 返回从头开始的尽可能多的元素,
    //直到遇到第一个false结果,如果第一个值不满足断言条件,将返回一个空的 Stream
        List<Integer> list= Arrays.asList(1,3,5,2,4,6);
        list.stream()
            .takeWhile(x->x<4)
            .forEach(System.out::println);
	结果为:1,3
	
	dropWhile:与 takeWhile相反,返回剩余的元素,和takeWhile方法形成互补
        List<Integer> list1= Arrays.asList(1,3,5,2,4,6);
        list1.stream()
                .dropWhile(x->x<4)
                .forEach(System.out::println);
	结果为:5,2,4,6

	ofNullable:此方法返回一个包含单个元素的顺序Stream。如果提供的元素为null,则此方法返回空Stream。
		//如果提供多个元素其中有null是没问题的
        Stream.of(1,2,3,null)
                .forEach(System.out::println);
        //jdk8中单个元素的时候不允许为null,jdk9中可以存放单个为null的元素
        Stream.of(null)
                .forEach(System.out::println);
	
	iterate:jdk8中的用法
        Stream.iterate(0,x->x+1)
                .limit(10) //进行限制输出
                .forEach(System.out::println);
     jdk9中可以有方法终止迭代
        Stream.iterate(0,x->x<10,x->x+1)
                .forEach(System.out::println);

Optional中增加Stream

List<String> list2 = new ArrayList<>();
        list2.add("1");
        list2.add("2");
        list2.add("3");
        list2.add("4");
        Optional.ofNullable(list2)
                .stream() //新添加的stream方法
                .forEach(System.out::println);

全新的HTTP客户端API

	HttpClient是一个对多个请求配置了公共信息的容器。所有的请求通过一个HttpClient进行发送。HttpClients是不可变的,通过HttpClient的newBuilder()创建返回。请求Builders被HttpRequest#newBuilder()来创建。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值