Java培训:深入解读函数式接口

news2024/9/21 16:44:40

函数式编程是一种编程规范或一种编程思想,简单可以理解问将运算或实现过程看做是函数的计算。 Java8为了实现函数式编程,提出了3个重要的概念:Lambda表达式、方法引用、函数式接口。现在很多公司都在使用lambda表达式进行代码编写,甚至知名的Java的插件也都在Lambda,比如数据库插件MybatisPlus。Lambda表达式的使用是需要函数式接口的支持,即lambda表达式的核心就是使用大量的函数式接口。本文带领大家全面了解函数式接口的定义和使用。

  一、文章导读

  函数式接口概述

  自定义函数式接口

  常用函数式接口

  函数式接口的练习

  二、函数式接口概述

1.函数式接口定义

  如果接口里只有一个抽象方法,那么就是函数式接口,可以使用注解(@FunctionalInterface)检测该接口是否是函数式接口,即只能有一个抽象方法。

  注意事项

  函数式接口里可以定义默认方法:默认方法有方法体,不是抽象方法,符合函数式接口的定义要求。

  函数式接口里可以定义静态方法:静态方法也不是抽象方法,是一个有具体方法实现的方法,同样也符合函数式接口的定义的。

  函数式接口里可以定义Object里的public方法(改成抽象方法):虽然它们是抽象方法,却不需要覆盖重写,因为所有接口的实现类都是Object类的子类,而在Object类中有这些方法的具体的实现。

  2.函数式接口格式

```java
修饰符 interface 接口名称 {//抽象方法publicabstract 返回值类型 方法名称(可选参数信息);//默认方法publicdefault 返回值类型 方法名称(可选参数信息){//代码...        }//静态方法publicstatic 返回值类型 方法名称(可选参数信息){//代码...        }//Object类的public方法变成抽象方法publicabstractbooleanequals(Object obj);publicabstractStringtoString();}
```

  三、自定义函数式接口

自定义函数式接口举例

  由于接口当中抽象方法的`public abstract`是可以省略的,所以定义一个函数式接口很简单:

```java
@FunctionalInterfacepublicinterfaceMyFunctionalInterface{//抽象方法publicabstractvoidmethod();//Object类的public方法变成抽象方法publicabstractbooleanequals(Object obj);publicabstractStringtoString();//默认方法publicdefaultvoidshow(String s){//打印小写System.out.println(s.toLowerCase());}//静态方法publicstaticvoidprint(String s){//打印大写System.out.println(s.toUpperCase());}}
```

  

2.自定义函数式接口的应用

  对于刚刚定义好的`MyFunctionalInterface`函数式接口,典型使用场景就是作为方法的参数:

```java
publicclassDemo01FunctionalInterface{publicstaticvoidmain(String[] args){// 调用使用函数式接口的方法show(()->{System.out.println("Lambda执行了");});}//定义方法使用函数式接口作为参数publicstaticvoidshow(MyFunctionalInterface mfi){//调用自己定义的函数式接口
        mfi.method();String s = mfi.toString();System.out.println(s);boolean result = mfi.equals(mfi);System.out.println(result);
        mfi.show("world");MyFunctionalInterface.print("function");}}
```

  

3.运行结果:

```
Lambda执行了
Demo01FunctionalInterface$$Lambda$1/1078694789@3d075dc0true
world
FUNCTION
```

  

四、常用函数式接口

  前面我们自己定义了一个函数式接口,对于一些常用的函数式接口,每次自己定义非常麻烦。JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在`java.util.function`包中被提供。这样的接口有很多,下面是最简单的几个接口及使用示例。

Supplier接口

  

`java.util.function.Supplier`接口,它意味着"供给" , 对应的Lambda表达式需要“**对外提供**”一个符合泛型类型的对象数据。

  

1.1.抽象方法 : get

  Supplier`接口中包含一个抽象方法` T get(): 用来获取一个泛型参数指定类型的对象数据。

```java

publicclassDemo02Supplier{publicstaticvoidmain(String[] args){int num =getNum(()->{returnnewRandom().nextInt();});System.out.println(num);}publicstaticintgetNum(Supplier<Integer> supplier){int num = supplier.get();return num;}}
```

  

1.2.求集合元素最大值

  使用`Supplier`接口作为方法参数类型,通过Lambda表达式求出List集合(存储int数据)中的最大值。提示:接口的泛型请使用`java.lang.Integer`类。

  代码示例:

```java
publicclassDemo03Supplier{publicstaticvoidmain(String[] args){List<Integer> list =newArrayList<>();Collections.addAll(list,10,8,20,3,5);printMax(()->{returnCollections.max(list);});}privatestaticvoidprintMax(Supplier<Integer> supplier){int max = supplier.get();System.out.println(max);}}
```

  

2. Consumer接口

  `java.util.function.Consumer`接口则正好相反,它不是生产一个数据,而是**消费**一个数据,其数据类型由泛型参数决定。

  2.1.抽象方法:accept

  `Consumer`接口中包含抽象方法`void accept(T t)`: 消费一个指定泛型的数据。

  代码示例:

```java
importjava.util.function.Consumer;//接收一个输入参数x,把x的值扩大2倍后,再+3做输出//类似于数学中的函数: f(x) = 2*x + 3publicclassDemo04Consumer{publicstaticvoidmain(String[] args){int x =3;consumeIntNum(x,(Integer num)->{System.out.println(2*num+3);});}/*
        定义方法,使用函数式接口Consumer作为方法参数
    */privatestaticvoidconsumeIntNum(int num,Consumer<Integer> function ){
        function.accept(num);}}
```

#### 2.2.默认方法:andThen

如果一个方法的参数和返回值全都是`Consumer`类型,那么就可以实现效果:消费一个数据的时候,首先做一个操作,然后再做一个操作,实现组合。而这个方法就是`Consumer`接口中的default方法`andThen`。下面是JDK的源代码:

```java
defaultConsumer<T>andThen(Consumer<?superT> after){Objects.requireNonNull(after);return(T t)->{accept(t); after.accept(t);};}
```

  

2.2.默认方法:andThen

  如果一个方法的参数和返回值全都是`Consumer`类型,那么就可以实现效果:消费一个数据的时候,首先做一个操作,然后再做一个操作,实现组合。而这个方法就是`Consumer`接口中的default方法`andThen`。下面是JDK的源代码:

```java
defaultConsumer<T>andThen(Consumer<?superT> after){Objects.requireNonNull(after);return(T t)->{accept(t); after.accept(t);};}
```

  

> 备注:`java.util.Objects`的`requireNonNull`静态方法将会在参数为null时主动抛出`NullPointerException`异常。这省去了重复编写if语句和抛出空指针异常的麻烦。

  > `andThen`是默认方法,由Consumer的对象调用,而且参数和返回值都是Consumer对象

  要想实现组合,需要两个或多个Lambda表达式即可,而`andThen`的语义正是“一步接一步”操作。例如两个步骤组合的情况:

  代码示例:

```java
//接收一个字符串,先按照大写打印,再按照小写打印/*
    toUpperCase(): 把字符串变成大写
    toLowerCase(): 把字符串变成小写
 */publicclassDemo05Consumer{publicstaticvoidmain(String[] args){String s ="Hello";//lambda标准格式fun(s,(String str)->{System.out.println(s.toUpperCase());},(String str)->{System.out.println(s.toLowerCase());});}/*
        定义方法,参数是Consumer接口
        因为要消费两次,所以需要两个Consumer接口作为参数
     */publicstaticvoidfun(String s,Consumer<String> con1,Consumer<String> con2){//先消费一次
        con1.accept(s);//再消费一次
        con2.accept(s);}}
```

  运行结果将会首先打印完全大写的HELLO,然后打印完全小写的hello。但是我们却没有使用andThen方法,其实我上面的写法,就是andThen底层的代码实现。

  为了方便大家理解,下面我们使用andThen方法进行演示。

```java
publicclassDemo06Consumer{publicstaticvoidmain(String[] args){String s ="HelloWorld";//2.lambda标准格式fun(s,(String str)->{System.out.println(s.toUpperCase());},(String str)->{System.out.println(s.toLowerCase());});}/*
        定义方法,参数是Consumer接口
        因为要消费两次,所以需要两个Consumer接口作为参数
     */publicstaticvoidfun(String s,Consumer<String> con1,Consumer<String> con2){

        con1.andThen(con2).accept(s);}}
```

  运行结果将会首先打印完全大写的HELLO,然后打印完全小写的hello。

  andThen原理分析图解:

  

  ```txt

  注意:

  1.con1调用andThen方法,传递参数con2,所以anThen方法内部的this就是con1,after就是con2

  2.andThen方法内部调用accept方法,前面隐藏了一个this,this代表调用andThen方法的对象,就是con1

  3.andThen方法内部的t是谁?就是最后调用方法accept传递的s

  this.accept(t) <==> con1.accept(s) ①

  4.con1调用andThen方法时传递的参数是con2,所以andThen方法内部的after就是con2

  after.accept(t) <==> con2.accept(s) ②

  5.通过分析,我们发现①和②中的内容,就是之前不用andThen方法,自己进行调用的过程

  6.以上分析,仍然是按照面向对象中方法调用的思路展开的,但实质上,我们要注意,Consumer接口中的andThen方法,返回的是一个Consumer,里面采用的是lambda表达式,其实是在做函数模型的拼接,把两个函数模型con1和con2拼接出一个新的模型,返回新的模型。所以con1.andThen(con2)是把con1和con2拼接成一个新的Consumer,返回的是lambda表达式的形式

  最后调用accept(s)方法时,其实执行的是lambda表达式{}中的代码

、、、

  3. Function接口

  `java.util.function.Function`接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。有进有出,所以称为“函数Function”。

  3.1.抽象方法:apply

  `Function`接口中最主要的抽象方法为:`R apply(T t)`,根据类型T的参数获取类型R的结果。

  代码示例:

  将`String`类型转换为`Integer`类型。

```java
/*
    java.util.function.Function<T,R>: 转换型接口
        泛型T: 转换前的类型
        泛型R: 转换后的类型

        抽象方法:
            R apply(T t): 根据类型T的参数获取类型R的结果 把参数t转换成R类型的结果

        "123" --> 123

        需求:
            给你一个String类型的数字,给我转换成int数字
            分析:
                用Function接口
                    T: 转换前的类型, String
                    R: 转换后的类型, Integer
 */publicclassDemo07Function{publicstaticvoidmain(String[] args){String s ="123";//lambda标准格式fun(s,(String str)->{returnInteger.parseInt(str);});}/*
        定义方法,使用Function接口作为参数
     */publicstaticvoidfun(String s,Function<String,Integer> function){Integer num = function.apply(s);System.out.println(num);}}
```

  3.2.默认方法:andThen

  `Function`接口中有一个默认的`andThen`方法,用来进行组合操作。JDK源代码如:

```java
default<V>Function<T,V>andThen(Function<?superR,?extendsV> after){Objects.requireNonNull(after);return(T t)-> after.apply(apply(t));}
```

  该方法同样用于“先做什么,再做什么”的场景,和`Consumer`中的`andThen`差不多:

  代码示例:

  将String的数字,转成int数字,再把int数字扩大10倍

```java
/*
    java.util.function.Function<T,R>: 转换型接口
        泛型T: 转换前的类型
        泛型R: 转换后的类型

        默认方法:
            default <V> Function<T, V> andThen(Function<R, V> after):
                先转换一次,再转换一次,一个挨着一个

        "123" --> 123 --> 1230 (扩大了10倍)

        需求:
            给你一个String类型的数字,
                给我转先换成int数字
                再给我把int数字扩大10倍
            分析:
                用2个Function接口
                    第一个Function接口
                        T: 转换前的类型, String
                        R: 转换后的类型, Integer
                    第二个Function接口:
                        T: 转换前的类型, Integer
                        R: 转换后的类型, Integer
 */publicclassDemo08Function{publicstaticvoidmain(String[] args){String s ="123";//lambda标准格式fun(s,(String str)->{returnInteger.parseInt(str);},(Integer num)->{return num*10;});}/*
        定义一个方法,有两个Function接口作为参数
     */publicstaticvoidfun(String s,Function<String,Integer> fun1,Function<Integer,Integer> fun2){//1.先转换一次Integer num1 = fun1.apply(s);//2.再转换一次Integer num2 = fun2.apply(num1);System.out.println(num2);}}
```

  第一个操作是将字符串解析成为int数字,第二个操作是乘以10。两个操作通过`andThen`按照前后顺序组合到了一起。运行结果将会打印1230。但是我们却没有使用andThen方法,其实我上面的写法,就是andThen底层的代码实现。

  > 请注意,Function的前置条件泛型和后置条件泛型可以相同。

  为了方便大家理解,下面我们使用andThen方法进行演示

  ```

publicclassDemo09Function{publicstaticvoidmain(String[] args){String s ="123";//lambda标准格式fun(s,(String str)->{returnInteger.parseInt(str);},(Integer num)->{return num*10;});}/*
        定义一个方法,有两个Function接口作为参数
     */publicstaticvoidfun(String s,Function<String,Integer> fun1,Function<Integer,Integer> fun2){Integer num3 = fun1.andThen(fun2).apply(s);System.out.println(num3);}}
```

  运行结果仍然是1230。

  andThen原理分析图解:

  

  ```txt

  注意:

  1.fun1调用andThen方法传递参数fun2,所以andThen方法内部的this就是fun1,after就是fun2

  2.andThen方法内部直接调用apply方法,前面隐藏了一个this,this代表调用andThen方法的对象,就是fun1

  3.andThen方法内部的t是谁?就是最后调用方法apply传递的s

  this.apply(t) <==> Integer num1 = fun1.apply(s) ①

  4.fun1调用andThen方法时传递的参数是fun2,所以andThen方法内部的after就是fun2

  after.apply(this.apply(t)) <==> Integer num2 = fun2.apply(num1) ②

  5.通过分析,我们发现①和②中的内容,就是之前不用andThen方法,我们自己进行调用的过程

  6.以上分析,仍然是按照面向对象中方法调用的思路展开的,但实质上,我们要注意,Function接口中的andThen方法,返回的是一个Function,里面采用的是lambda表达式,其实是在做函数模型的拼接,把两个函数模型fun1和fun2拼接出一个新的模型,返回新的模型。所以fun1.andThen(fun2)是把fun1和fun2拼接成一个新的Function,返回的是lambda表达式的形式

  最后调用accept(s)方法时,其实执行的是lambda表达式{}中的代码

  4. Predicate接口

  有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用`java.util.function.Predicate`接口。

  4.1.抽象方法:test

  `Predicate`接口中包含一个抽象方法:`boolean test(T t)`。用于条件判断的场景:

```java
//1.练习:判断字符串长度是否大于5//2.练习:判断字符串是否包含"H"publicclassDemo10Predicate{publicstaticvoidmain(String[] args){String str ="helloWorld";//1.练习:判断字符串长度是否大于5//lambda标准格式fun(str,(String s)->{return s.length()>5;});System.out.println("-----------------");//2.练习:判断字符串是否包含"H"//lambda标准格式fun(str,(String s)->{return s.contains("H");});}/*
        定义一个方法,参数是Predicate接口
     */publicstaticvoidfun(String s,Predicate<String>predicate){boolean result = predicate.test(s);System.out.println(result);}}
```

  条件判断的标准是传入的Lambda表达式逻辑,只要字符串长度大于5则认为很长。

  4.2.默认方法:and

  既然是条件判断,就会存在与、或、非三种常见的逻辑关系。其中将两个`Predicate`条件使用“与”逻辑连接起来实现“**并且**”的效果时,可以使用default方法`and`。其JDK源码为:

```java
defaultPredicate<T>and(Predicate<?superT> other){Objects.requireNonNull(other);return(t)->test(t)&& other.test(t);}
```

  代码示例:

  判断一个字符串既要包含大写“H”,又要包含大写“W”

```java
publicclassDemo11Predicate{publicstaticvoidmain(String[] args){String str ="HelloWorld";//1.练习:判断一个字符串既要包含大写“H”,又要包含大写“W”//lambda标准格式fun1(str,(String s)->{return s.contains("H");},(String s)->{return s.contains("W");});System.out.println("------------");fun2(str,(String s)->{return s.contains("H");},(String s)->{return s.contains("W");});}/*
        演示and方法
        需要两个Predicate作为参数
        fun1方法没有使用and方法,就是p1和p2分别调用test方法,
        然后把结果进行&&运算--其实这是and方法的底层实现
     */publicstaticvoidfun(String s,Predicate<String> p1,Predicate<String> p2){//先判断一次boolean result1 = p1.test(s);//再判断一次boolean result2 = p2.test(s);//进行&&运算boolean result = result1&&result2;System.out.println(result);}/*
        演示and方法
        需要两个Predicate作为参数
        
     */publicstaticvoidfun2(String s,Predicate<String> p1,Predicate<String> p2){boolean result = p1.and(p2).test(s);System.out.println(result);}}

```

  4.3.默认方法:or

  与`and`的“与”类似,默认方法`or`实现逻辑关系中的“**或**”。JDK源码为:

```java
defaultPredicate<T>or(Predicate<?superT> other){Objects.requireNonNull(other);return(t)->test(t)|| other.test(t);}
```

  代码示例:

  字符串包含大写H或者包含大写W”

```java
publicclassDemo12Predicate{publicstaticvoidmain(String[] args){String str ="Helloworld";//1.练习:判断一个字符串包含大写“H”或者包含大写“W”//lambda标准格式fun1(str,(String s)->{return s.contains("H");},(String s)->{return s.contains("W");});System.out.println("------------");fun2(str,(String s)->{return s.contains("H");},(String s)->{return s.contains("W");});}/*
        演示or方法
        需要两个Predicate作为参数
        fun1方法没有使用or方法,就是p1和p2分别调用test方法,
        然后把结果进行||运算--其实这是or方法的底层实现
     */publicstaticvoidfun(String s,Predicate<String> p1,Predicate<String> p2){//先判断一次boolean result1 = p1.test(s);//再判断一次boolean result2 = p2.test(s);//进行||运算boolean result = result1||result2;System.out.println(result);}/*
        演示or方法
        需要两个Predicate作为参数
        
     */publicstaticvoidfun2(String s,Predicate<String> p1,Predicate<String> p2){boolean result = p1.or(p2).test(s);System.out.println(result);}}

```

  关于and和or方法的原理,可以参考andThen方法原理

  4.4.默认方法:negate

  “与”、“或”已经了解了,剩下的“非”(取反)也会简单。默认方法`negate`的JDK源代码为:

```java
defaultPredicate<T>negate(){return(t)->!test(t);}
```

  从实现中很容易看出,它是执行了test方法之后,对结果boolean值进行“!”取反而已。一定要在`test`方法调用之前调用`negate`方法,正如`and`和`or`方法一样:

```java
importjava.util.function.Predicate;publicclassDemo13Predicate{privatestaticvoidmethod(Predicate<String> predicate,String str){boolean veryLong = predicate.negate().test(str);System.out.println("字符串很长吗:"+ veryLong);}publicstaticvoidmain(String[] args){method(s -> s.length()<5,"Helloworld");}}
```

  

五、总结

  本文通过具体的例子,演示了函数式接口的定义和使用。以及常用的函数式接口。并给出了相关的练习题目。对于部分函数式接口中的默认方法,进行了图解分析,让你更加深刻的理解函数式接口的思想和目的。在以后实际的编程过程中,对于集合的操作,可以通过Stream流完成,而Stream流中的很多方法的参数都是函数式接口,通过本文的学习,你已经掌握了函数式接口的使用,相信后面学习Stream流是非常容易的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/377791.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

花7000报了培训班,3个月后我成功“骗”进了阿里,月薪拿16K....

“月薪4000元不如报名学IT&#xff0c;挑战年薪百万”这是大多数培训班在互联网上宣传的口号&#xff0c;简单的16个字却戳中了很多人的痛点&#xff0c;同龄人买车买房&#xff0c;自己却拿着微薄的工资连好一点的房子都租不起&#xff0c;这句口号 彻底激起了底层员工的焦虑&…

Spring上下文生命周期

基于入口来分析 import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;Configuration ComponentScan public cl…

飞行机器人专栏(十)-- 异构多视角视觉系统

感知系统架构为满足天空端主控制器的诸如RGB-D图像处理等大容量数据吞吐、高速并行计算、实时运动控制以及通信和可视化任务的计算算力需求&#xff0c;同时优化功耗表现&#xff0c;采用了结构紧凑、功耗表现优异的边缘计算硬件NVIDA IJetson AGXOrin 。该开发者套件包含高性能…

Python学习笔记202302

1、numpy.empty 作用&#xff1a;根据给定的维度和数值类型返回一个新的数组&#xff0c;其元素不进行初始化。 用法&#xff1a;numpy.empty(shape, dtypefloat, order‘C’) 2、logging.debug 作用&#xff1a;Python 的日志记录工具&#xff0c;这个模块为应用与库实现了灵…

可用于标记蛋白质216699-36-4,6-ROX,SE,6-羧基-X-罗丹明琥珀酰亚胺酯

一.6-ROX&#xff0c;SE产品描述&#xff1a;6-羧基-X-罗丹明琥珀酰亚胺酯&#xff08;6-ROX&#xff0c;SE&#xff09;是一种用于寡核苷酸标记和自动DNA测序的荧光染料&#xff0c;可用于标记蛋白质&#xff0c;寡核苷酸和其他含胺分子的伯胺&#xff08;-NH2&#xff09;。西…

Git中遇到的问题

文章目录Clone克隆bytes of body are still expectedunable to access此文章是自己在Git操作时遇到的问题&#xff0c;先开个坑记录下来&#xff0c;如果以后还遇到了Git上的其他问题&#xff0c;会在后面进行添加。Clone克隆 bytes of body are still expected Clone失败信息…

【Redis】Java客户端JedisSpringDataRedis入门(三)

&#x1f697;Redis学习第三站~ &#x1f6a9;起始站&#xff1a;【Redis】概述&环境搭建(一) &#x1f6a9;本文已收录至专栏&#xff1a;数据库学习之旅 &#x1f44d;希望您能有所收获 在上一篇中我们学习了Redis常见命令的使用&#xff0c;显然&#xff0c;我们不可能一…

Day21【元宇宙的实践构想07】—— 元宇宙与人工智能

&#x1f483;&#x1f3fc; 本人简介&#xff1a;男 &#x1f476;&#x1f3fc; 年龄&#xff1a;18 &#x1f91e; 作者&#xff1a;那就叫我亮亮叭 &#x1f4d5; 专栏&#xff1a;元宇宙 0.0 写在前面 “元宇宙”在2021年成为时髦的概念。元宇宙到底是什么&#xff1f;元宇…

[架构之路-123]-《软考-系统架构设计师》-操作系统-2-操作系统原理 - 存储层次结构与存储管理(寄存器、Cache、MMU、内存、外存、页表)

前言&#xff1a;操作系统的本质就是创建一个并发的应用程序执行的环境&#xff0c;使得各种应用程序可以动态、共享相同的计算机物理硬件资源&#xff0c;计算机的三大物理资源包括&#xff1a;CPU内存外设应用程序&#xff08;管理应用程序&#xff09;&#xff1a;以进程和现…

线性代数学习-1

线性代数学习-1行图像和列图像行图像列图像总结本文转载于https://herosunly.blog.csdn.net/article/details/88698381 该文章本人认为十分有用&#xff0c;便自己敲一遍笔记加固印象原文链接 原文这个笔记感觉比我老师讲的更加透彻&#xff0c;清晰。很好的展示了线性代数的原…

【MySQL】数据库中锁和事务的相关知识点

1.事务的四大特点 原子性&#xff1a;事务中的所有操作要么都成功&#xff0c;要么都失败。所有的操作是一个不可分割的单位。一致性&#xff1a;一致性指的是事务执行前后&#xff0c;数据从一个合法性状态转移到另一个合法性状态。这个状态和业务有关&#xff0c;是自己定义…

基于ssm框架大学生社团管理系统(源码+数据库+文档)

一、项目简介 本项目是一套基于ssm框架大学生社团管理系统&#xff0c;主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目可以直接作为bishe使用。 项目都经过严格调试&#xff0c;确保可…

在线文本翻译能力新增14个直译模型,打造以中文为轴心语言的翻译系统

经济全球化的今天&#xff0c;人们在工作和生活中经常会与外语打交道。相较传播性较广的英语而言&#xff0c;其他语种的识别和阅读对大多数人来说是一件难事&#xff0c;此时就需要借助语言翻译软件来帮助理解。 华为 HMS Core 机器学习服务&#xff08;ML Kit&#xff09;翻…

JVM详解——内存结构

文章目录内存结构1、 运行时数据区2、虚拟机栈3、本地方法栈4、程序计数器5、 堆6、方法区7、运行时常量池8、内存溢出和内存泄漏9、 堆溢出内存结构 1、 运行时数据区 Java虚拟机在运行Java程序期间将管理的内存划分为不同的数据区&#xff0c;不同的区域负责不同的职能&…

[YOLO] yolo理解博客笔记

YOLO v2和V3 关于设置生成anchorbox&#xff0c;Boundingbox边框回归的过程详细解读 YOLO v2和V3 关于设置生成anchorbox&#xff0c;Boundingbox边框回归的个人理解https://blog.csdn.net/shenkunchang1877/article/details/105648111YOLO v1网络结构计算 Yolov1-pytorch版 …

ChatGPT修炼指南和它的电力畅想

近期&#xff0c;ChatGPT刷屏各大社交平台&#xff0c;无疑成为人工智能界最靓的仔&#xff01; 身为一款“会说话”的聊天机器人程序&#xff0c;它与前辈产品Siri、小度、微软小冰等有什么不同&#xff1f;先来听听小伙伴们怎么说。 ChatGPT何以修炼得这么强大&#xff1f;…

什么叫骨传导概念耳机,骨传导耳机的原理是什么

骨传导耳机在蓝牙耳机当中是属于十分特殊传输声音的一种方式&#xff0c;开放式传输声音&#xff0c;其使用优点也受到越来越多人的熟知和喜爱&#xff0c;但还有一部分朋友们不知道骨传导耳机传输声音的原理是啥&#xff0c;下面就给大家简单科普一下。骨传导耳机是利用内置的…

BurpSuite实战教程03-BurpSuite插件开发

burp插件开发 Burp Suite的强大除了自身提供了丰富的可供测试人员使用的功能外&#xff0c;其提供的支持第三方拓展插件的功能也极大地方便使用者编写自己的自定义插件。&#xff0c;Burp Suite支持的插件类型有Java、Python、Ruby三种。无论哪种语言的实现&#xff0c;开发者…

华为造车锚定智选模式, 起点赢家赛力斯驶入新能源主航道

文|螳螂观察 作者| 易不二 近日&#xff0c;赛力斯与华为的一纸联合业务深化合作协议&#xff0c;给了频频猜测赛力斯与华为之间关系的舆论一个明确的定调&#xff1a;智选模式已成为华为与赛力斯共同推动中国新能源汽车产业高质量发展的坚定选择。 自华为智能汽车业务开启零…

【Java】TCP网络编程(字节/符流)

文章目录概念TCP网络编程ServerSocketsocket使用区别和原理演示概念 TCP&#xff08;传输控制协议&#xff09;是一种面向连接的协议&#xff0c;用于在计算机网络中可靠地传输数据。TCP是Internet协议族中的一个核心协议&#xff0c;它在传输层提供可靠、有序、基于流的传输服…