JDK8新特性

本文深入探讨JDK8的新增特性,包括可变参数、增强for循环、Lambda表达式、Stream API、类加载机制及反射技术。详细介绍这些特性的使用方法、优缺点及其在实际编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值