java 函数式编程 示例_功能Java示例 第8部分–更多纯函数

java 函数式编程 示例

这是第8部分,该系列的最后一部分称为“示例功能Java”。

我在本系列的每个部分中开发的示例是某种“提要处理程序”,用于处理文档。 在上一期文章中,我们已经使用Vavr库看到了一些模式匹配,并且还将故障也视为数据 ,例如,采用了替代路径并返回到功能流程。

在本系列的最后一篇文章中,我将功能发挥到了极致 :一切都变成了功能。

如果您是第一次来,最好是从头开始阅读。 它有助于了解我们从何处开始以及如何在整个系列中继续前进。

这些都是这些部分:

  • 第1部分–从命令式到声明式
  • 第2部分–讲故事
  • 第3部分–不要使用异常来控制流程
  • 第4部分–首选不变性
  • 第5部分–将I / O移到外部
  • 第6部分–用作参数
  • 第7部分–将失败也视为数据
  • 第8部分–更多纯函数

我将在每篇文章发表时更新链接。 如果您通过内容联合组织来阅读本文,请查看我博客上的原始文章。

每次代码也被推送到这个GitHub项目 。

最大化运动部件

您可能已经听过Micheal Feathers的以下短语:

OO通过封装运动部件使代码易于理解。 FP通过最大程度地减少运动部件来使代码易于理解。

好的,让我们稍稍忘记上一期中的故障恢复,然后继续下面的版本:

 FeedHandler { class FeedHandler { List<Doc> handle(List<Doc> changes, Function<Doc, Try<Resource>> creator) { changes .findAll { doc -> isImportant(doc) } .collect { doc -> creator.apply(doc) }.map { resource -> setToProcessed(doc, resource) }.getOrElseGet { e -> setToFailed(doc, e) } } } private static boolean isImportant(doc) { doc.type == 'important' } private static Doc setToProcessed(doc, resource) { doc.copyWith( status: 'processed' , apiId: resource.id ) } private static Doc setToFailed(doc, e) { doc.copyWith( status: 'failed' , error: e.message ) }  } 

替换为功能类型

我们可以使用对函数接口类型的变量(例如PredicateBiFunction的引用来替换每种方法。

A)我们可以替换一个接受1个参数的方法,该方法返回一个布尔值

 private static boolean isImportant(doc) { doc.type == 'important'  } 

谓词

 private static Predicate<Doc> isImportant = { doc -> doc.type == 'important'  } 

B),我们可以替换一个接受2个参数并返回结果的方法

 private static Doc setToProcessed(doc, resource) { ...  }  private static Doc setToFailed(doc, e) { ...  } 

具有BiFunction

 private static BiFunction<Doc, Resource, Doc> setToProcessed = { doc, resource -> ...  }  private static BiFunction<Doc, Throwable, Doc> setToFailed = { doc, e -> ...  } 

为了实际调用封装在(Bi)Function中的逻辑,我们必须对其调用apply 。 结果如下:

 FeedHandler { class FeedHandler { List<Doc> handle(List<Doc> changes, Function<Doc, Try<Resource>> creator) { changes .findAll { isImportant } .collect { doc -> creator.apply(doc) .map { resource -> setToProcessed.apply(doc, resource) }.getOrElseGet { e -> setToFailed.apply(doc, e) } } } private static Predicate<Doc> isImportant = { doc -> doc.type == 'important' } private static BiFunction<Doc, Resource, Doc> setToProcessed = { doc, resource -> doc.copyWith( status: 'processed' , apiId: resource.id ) } private static BiFunction<Doc, Throwable, Doc> setToFailed = { doc, e -> doc.copyWith( status: 'failed' , error: e.message ) }  } 

将所有输入移至功能本身

我们将所有内容移至方法签名,以便FeedHandler的handle方法的调用者可以提供自己的那些功能的实现。

方法签名将更改为:

 List<Doc> handle(List<Doc> changes, Function<Doc, Try<Resource>> creator) 

 List<Doc> handle(List<Doc> changes, Function<Doc, Try<Resource>> creator, Predicate<Doc> filter, BiFunction<Doc, Resource, Doc> successMapper, BiFunction<Doc, Throwable, Doc> failureMapper) 

其次,我们将重命名原始(静态) 谓词BiFunction变量

  • isImportant
  • setToProcessed
  • setToFailed

转换为类顶部的新常量 ,反映它们的新作用。

  • DEFAULT_FILTER
  • DEFAULT_SUCCESS_MAPPER
  • DEFAULT_FAILURE_MAPPER

客户端可以完全控制是否将默认实现用于某些功能,或者何时需要接管自定义逻辑。

例如,当仅需要定制故障处理时,可以这样调用handle方法:

 BiFunction<Doc, Throwable, Doc> customFailureMapper = { doc, e -> doc.copyWith( status: 'my-custom-fail-status' , error: e.message )  }  new FeedHandler().handle(..., FeedHandler.DEFAULT_FILTER, FeedHandler.DEFAULT_SUCCESS_MAPPER, customFailureMapper ) 

如果您的语言支持,则可以通过分配默认值来确保客户端实际上不必提供每个参数。 我正在使用支持将默认值分配给方法中的参数的Apache Groovy :

 List<Doc> handle(List<Doc> changes, Function<Doc, Try<Resource>> creator, Predicate<Doc> filter = DEFAULT_FILTER, BiFunction<Doc, Resource, Doc> successMapper = DEFAULT_SUCCESS_MAPPER, BiFunction<Doc, Throwable, Doc> failureMapper = DEFAULT_FAILURE_MAPPER) 

在我们将应用另一个更改之前,请看一下代码:

 FeedHandler { class FeedHandler { private static final Predicate<Doc> DEFAULT_FILTER = { doc -> doc.type == 'important' } private static final BiFunction<Doc, Resource, Doc> DEFAULT_SUCCESS_MAPPER = { doc, resource -> doc.copyWith( status: 'processed' , apiId: resource.id ) } private static final BiFunction<Doc, Throwable, Doc> DEFAULT_FAILURE_MAPPER = { doc, e -> doc.copyWith( status: 'failed' , error: e.message ) } List<Doc> handle(List<Doc> changes, Function<Doc, Try<Resource>> creator, Predicate<Doc> filter = DEFAULT_FILTER, BiFunction<Doc, Resource, Doc> successMapper = DEFAULT_SUCCESS_MAPPER, BiFunction<Doc, Throwable, Doc> failureMapper = DEFAULT_FAILURE_MAPPER) { changes .findAll { filter } .collect { doc -> creator.apply(doc) .map { resource -> successMapper.apply(doc, resource) }.getOrElseGet { e -> failureMapper.apply(doc, e) } } }  } 

介绍两者

您是否注意到以下部分?

 .collect { doc -> creator.apply(doc) .map { resource -> successMapper.apply(doc, resource) }.getOrElseGet { e -> failureMapper.apply(doc, e) }  } 

请记住, creator的类型是

 Function<Doc, Try<Resource>> 

表示它返回一个Try 。 我们在第7部分中介绍了Try ,它是从Scala等语言中借来的。

幸运的是, collect { doc的“ doc”变量仍在传递给我们需要它的successMapperfailureMapper 范围内 ,但是Try#map的方法签名(接受一个Function )与我们的successMapper (即一个BiFunctionTry#getOrElseGet也是Try#getOrElseGet ,它也只需要一个Function

从Try Javadocs:

  • map(Function <?super T,?extended U>映射器)
  • getOrElseGet(Function <?super Throwable,?extended T> other)

简而言之,我们需要从

  1. BiFunction <文档,资源,文档> successMapper
  2. BiFunction <文档,Throwable,文档> failureMapper

  1. 函数<资源,文档> successMapper
  2. 函数<Throwable,Doc> failureMapper

同时仍然可以将原始文档作为输入

让我们介绍两个简单的类型,它们封装了2个BiFunction的2个参数:

 class CreationSuccess { Doc doc Resource resource  }  class CreationFailed { Doc doc Exception e  } 

我们将论点从

  1. BiFunction <文档,资源,文档> successMapper
  2. BiFunction <文档,Throwable,文档> failureMapper

改为功能

  1. 函数<CreationSuccess,Doc> successMapper
  2. 函数<CreationFailed,Doc> failureMapper

现在, handle方法如下所示:

 List<Doc> handle(List<Doc> changes, Function<Doc, Try<Resource>> creator, Predicate<Doc> filter, Function<CreationSuccess, Doc> successMapper, Function<CreationFailed, Doc> failureMapper) { changes .findAll { filter } .collect { doc -> creator.apply(doc) .map(successMapper) .getOrElseGet(failureMapper) }  } 

…… 但是还不行

Try使mapgetOrElseGet需要分别。 一个

  • 函数<资源,文档> successMapper
  • 函数<Throwable,Doc> failureMapper

这就是为什么我们需要将其更改为另一个著名的FP结构,称为Either

幸运的是Vavr有要么太。 它的Javadoc说:

任一代表两种可能的值。

通常使用这两种类型来区分正确的值(“正确”)或错误的值。

它变得非常抽象:

一个Either可以是Either.Left或Either.Right。 如果给定的Either是Right并投影到Left,则Left操作对Right值没有影响。 如果给定的Either是Left并投影到Right,则Right操作对Left值没有影响。 如果将“左”投影到“左”或将“右”投影到“右”,则操作会生效。

让我解释以上神秘的文档。 如果我们更换

 Function<Doc, Try<Resource>> creator 

通过

 Function<Doc, Either<CreationFailed, CreationSuccess>> creator 

我们将CreationFailed分配给“ left”参数,按照惯例通常会保留错误(请参见Either上的Haskell文档 ), CreationSuccess是“ right”(和“正确”)值。

在运行时,该实现曾经返回Try ,但是现在可以返回Either.Right ,如果成功,例如

 return Either.right( new CreationSuccess( doc: document, resource: [id: '7' ] )  ) 

Either.Left ,但发生故障时除外- 两者都包括原始文档 。 是。

因为现在类型最终匹配,所以我们终于压扁了

 .collect { doc -> creator.apply(doc) .map { resource -> successMapper.apply(doc, resource) }.getOrElseGet { e -> failureMapper.apply(doc, e) }  } 

进入

 .collect { doc -> creator.apply(doc) .map(successMapper) .getOrElseGet(failureMapper)  } 

现在, handle方法如下所示:

 List<Doc> handle(List<Doc> changes, Function<Doc, Either<CreationFailed, CreationSuccess>> creator, Predicate<Doc> filter, Function<CreationSuccess, Doc> successMapper, Function<CreationFailed, Doc> failureMapper) { changes .findAll { filter } .collect { doc -> creator.apply(doc) .map(successMapper) .getOrElseGet(failureMapper) }  } 

结论

我可以说我已经实现了开始时设定的大多数目标:

  • 是的,我设法避免了重新分配变量
  • 是的,我设法避免了可变数据结构
  • 是的,我设法避免了状态 (至少在FeedHandler中)
  • 是的,我设法支持函数 (使用某些Java内置函数类型和某些第三方库Vavr)

我们已经将所有内容移至函数签名,以便FeedHandler的handle方法的调用者可以直接传递正确的实现。 如果您从头到尾回顾原始版本,您会注意到在处理更改列表时,我们仍然承担所有责任:

  • 通过某些条件过滤文档列表
  • 为每个文档创建资源
  • 成功创建资源后执行一些操作
  • 无法创建资源时执行其他操作

然而,在第一部分中,这些责任是势在必行写出来,for语句声明,都在一个大聚集在一起handle方法。 现在,最后,每个决定或动作都由具有抽象名称的函数表示,例如“过滤器”,“创建者”,“ successMapper”和“ failureMapper”。 实际上,它成为一个高阶函数,以多个函数之一作为参数。 提供所有参数的责任已经转移到了客户的上层。 如果您查看GitHub项目,您会注意到,对于这些示例,我不得不不断更新单元测试。

有争议的部分

在实践中,如果不需要,我可能不会编写我的(Java)业务代码,例如FeedHandler类在传递通用Java函数类型(即FunctionBiFunctionPredicateConsumerSupplier )方面的使用方式所有这些极端的灵活性。 所有这些都是以可读性为代价的。 是的,Java是一种静态类型的语言,因此,使用泛型时,必须在所有类型参数中明确使用一种语言,从而导致以下功能的签名困难:

 handle(List<Doc> changes,  Function<Doc, Either<CreationFailed, CreationSuccess>> creator,  Predicate<Doc> filter,  Function<CreationSuccess, Doc> successMapper,  Function<CreationFailed, Doc> failureMapper) 

在普通JavaScript中,您将没有任何类型,并且您必须阅读文档以了解每个参数的期望。

 handle = function (changes, creator, filter, successMapper, failureMapper) 

但是,这是一个折衷方案。 Groovy中,也是一个JVM语言, 可以让我省略所有的例子类型的信息在这个系列中,甚至允许我使用闭包(象Java lambda表达式)是在Groovy中的函数式编程范式的核心。

更极端的做法是在类级别指定所有类型,以使客户端具有最大的灵活性,以便为不同的FeedHandler实例指定不同的类型。

 handle(List<T> changes,  Function<T, Either<R, S>> creator,  Predicate<T> filter,  Function<S, T> successMapper,  Function<R, T> failureMapper) 

什么时候合适?

  • 如果您完全控制代码,则在特定上下文中使用它来解决特定问题时,这将过于抽象而无法产生任何收益。
  • 但是,如果我将一个库或框架开源(或者在一个组织内向其他团队或部门使用),该库或框架正在各种不同的用例中使用,那么我可能不会事先想到,为灵活性而设计可能值得。 让呼叫者决定如何过滤以及成功或失败的构成是明智之举。

最终,上述内容在API设计 ,是和解耦方面都有所涉及,但是在典型的Enterprise Java Java项目中“使一切成为函数”可能需要与您和您的团队成员进行一些讨论。 多年来,一些同事已经习惯了一种更传统,更惯用的代码编写方式。

好的零件

  • 我绝对希望使用不可变的数据结构 (和“参照透明性”)来帮助推断我的数据所处的状态。想想Collections.unmodifiableCollection的集合。 在我的示例中,我将Groovy的@Immutable用于POJO,但在普通的Java库(例如Immutables , AutoValue或Project Lombok)中也可以使用。
  • 最大的改进实际上是导致了一种更具功能性的样式:使代码讲故事 ,这主要是关于分离关注点并适当地命名事物。 在任何编程风格(即使是OO:D)中,这都是一个好习惯,但这确实消除了混乱,并允许引入(纯)函数。
  • 在Java中,我们习惯于以特定方式进行异常处理,以至于像我这样的开发人员很难提出其他解决方案。 诸如Haskell之类的功能语言仅返回错误代码,因为“ Niklaus Wirth认为异常是GOTO的转世,因此省略了它们” 。 在Java中,可以使用CompletableFuture或…
  • 通过引入第3方库(例如Vavr)可在您自己的代码库中使用的特定类型(例如TryEither )可以极大地帮助您启用以FP样式编写的更多选项 ! 我以流畅的方式编写“成功”或“失败”路径并具有很高的可读性而感到非常着迷。

Java不是F#的Scala或Haskell或Clojure,它最初遵循的是面向对象编程(OOP)范例,就像C ++,C#,Ruby等一样,但是在Java 8中引入了lambda表达式并结合了一些很棒的功能之后如今,开放源代码库如今,开发人员绝对可以选择OOP和FP必须提供的最佳元素

做系列的经验教训

我在很早以前就开始了这个系列的讨论 。 早在2017年,我发现自己在一段代码上进行了一些FP风格的重构,这启发了我去寻找一系列名为“ Functional Java by Example”的文章的示例 。 这成为我在每个批次中一直使用的FeedHandler代码。

那时我已经对所有的代码进行了更改,但是当我计划编写实际的博客文章时,我常常想到:“我只是不能展示重构,我必须进行实际解释!” 那就是我为自己设置陷阱的地方,因为在整个过程中,我坐下来写作的时间越来越少。 (任何写过博客的人都知道,简单地分享要点和撰写可理解的英语co的连贯段落在时间上的区别)

下次当我想到进行一系列学习时,我将向Google返回这些经验教训:

  1. 如果您不准备在发布新文章时每次准备发布的每期文章都更新所有链接,则不要在每篇文章的顶部都包含目录(TOC)。 如果将这些交叉发布到公司的公司博客中,则工作量是原来的2倍🙂
  2. 随着时间的流逝,您可能会得出自己宁愿偏离主要用例的结论,也就是刚开始使用的Big Coding Example。 我宁愿展示更多的FP概念(例如, 使用FP技术时的咖喱,记忆,懒惰,以及不同的心态),但我不能很好地适应以前完成的重构和我在一开始建立的TOC 。 如果您正在撰写有关特定概念的文章,通常会找到一个合适的示例来帮助说明手头的特定概念,并且仍然与读者相关。 随着时间的流逝,我将获得更好的洞察力,从而可以确定接下来要写的更好的东西以及要使用的更合适的示例。 下次,我将不得不寻找一种方法来(更好地:允许)给自己一些创作上的自由😉

  • 《功能性思维:语法惊人的范式 》,尼尔·福特(Neil Ford)着,它展示了FP思维的新方法,并且也以不同的方式处理问题。
  • 40分钟内的函数式编程 Russ Olsen的Youtube视频解释说:“这些数学家用379页证明1 + 1 = 2。 让我们看看我们可以从中吸取什么好主意。”
  • 为什么不对函数进行规范编程? 理查德·费尔德曼(Richard Feldman)的Youtube视频,他解释了为什么OOP变得非常流行,以及FP为何不是常态。 正如您所知,他是Elm核心团队的成员,与FP有一定的联系。
  • (耦合)控制的倒置有关“托管功能”的深思熟虑的文章。 您想要抽象吗?

如果您有任何意见或建议,我很想听听他们的意见!

编程愉快! 🙂


翻译自: https://www.javacodegeeks.com/2019/12/functional-java-by-example-part-8-more-pure-functions.html

java 函数式编程 示例

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

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

相关文章

html加css作品,我的影视作品,如何在博客园发布带有CSS样式的HTML

总结一下&#xff0c;我做过的视频&#xff1a;(顺便试试在博客园如何发HTML网页)发布网页总结&#xff1a;HTML可以正常发送&#xff0c;但最好将你要发布的html文件放在一个带有ID的div中&#xff0c;这样方便后期添加样式时通过ID添加&#xff0c;不会影响到网页中的其他布局…

FileInputStream

java.ioClass FileInputStream java.lang.Object java.io.InputStream java.io.FileInputStream 所有已实现的接口: Closeable public class FileInputStream extends InputStream FileInputStream 从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。 Fil…

android console命令,我们可以通过两种方式进入Android的console: 1. 直接执行命令emulator -shell; 2....

Don’t use /usr 这样子编译出来的busybox才不会安装到你主机的/usr目录下。一定要选上。4 执行make编译源码. 如果编译过程中产生无法找到头文件的错误, 可指定交叉编译器用到的头文件所在路径. 如 $make -I./home/jo/tool/arm-2008q3/arm-none-linux-gnueabi/lib…

selenium 示例_Selenium测试中所需的功能和示例

selenium 示例所需功能是用于声明一组基本要求&#xff08;例如浏览器&#xff0c;操作系统&#xff0c;浏览器版本等的组合&#xff09;的类&#xff0c;以对Web应用程序执行自动跨浏览器测试。 当我们尝试通过Selenium自动化测试来自动化测试脚本时&#xff0c;我们需要考虑…

java流与文件——正则表达式

【0】README 0.1&#xff09; 本文描述转自 core java volume 2&#xff0c; 旨在理解 java流与文件——正则表达式 的相关知识&#xff1b; 0.2&#xff09; there are my original source code below, and for them , please visit https://github.com/pacosonTang/core-ja…

pandoc讲html转换为pdf,mac下利用Pandoc、LaTeX 转换markdown成html,pdf

环境所使用的插件有pandoc,tlmgr,fc-listcssbrew install pandoc由于mac ox 系统生成pdf 须要找到对应的编码集 全部还须要去下载LaTeX&#xff0c;进行安装html5使用tlmgr工具安装全部要的包先进行更新&#xff0c;若是提示所须要的字体没有找到安装gitsudo tlmgr update --se…

java程序连接kafka_Java的Kafka:构建安全,可扩展的消息传递应用程序

java程序连接kafka使用Okta的身份管理平台轻松部署您的应用程序 使用Okta的API在几分钟之内即可对任何应用程序中的用户进行身份验证&#xff0c;管理和保护。 今天尝试Okta。 当今的用户希望可以通过其计算机&#xff0c;手机&#xff0c;平板电脑或任何其他设备访问您的应用…

信息系html5论文,基于HTML5的智力游戏设计电子信息工程本科学生毕业论文.doc

基于HTML5的智力游戏设计电子信息工程本科学生毕业论文本科学生毕业论文(设计)题目(中文)&#xff1a;基于HTML5的智力游戏设计(英文)&#xff1a;Design of Intelligent Game Based on HTML5姓 名 xxx学 号 xxx院 (系) 电子与信息工程学院专业、年级 电子信息工程指导教师 xxx…

优先队列——左式堆

【0】README 0.1&#xff09; 本文文字描述部分转自 数据结构与算法分析&#xff0c; 旨在理解 优先队列——左式堆 的基础知识&#xff1b; 0.2&#xff09; 本文核心思路均为原创&#xff0c; 源代码部分借鉴 数据结构与算法分析 &#xff1b; 0.3&#xff09; for origin…

Class类中的getEnclosing*、getDeclared*与getDeclaringClass的区别

一、getEnclosing* 当前类在……中闭合Class<?>getEnclosingClass() 返回底层类的立即封闭类。 Constructor<?>getEnclosingConstructor() 如果该 Class 对象表示构造方法中的一个本地或匿名类&#xff0c;则返回 Constructor 对象&#xf…

java联接pg库_Java14:使用Java 14的新记录联接数据库表

java联接pg库您是否知道可以使用Java 14的预览记录功能将数据库表连接到Java Stream中&#xff1f; 阅读这篇简短的文章&#xff0c;并了解如何使用Speedment Stream ORM完成它。 我们将从如何设置您的项目开始。 建立 下载Java 14 。 转到Speedment Initializer并下载您的项目…

html5遍历集合数据,HTMLCollection集合能打印出来值,但是无法获取每一个值。

var imgs $("#pictureQueryTable img").prevObject[0].images;下图是上面这句打印出来的结果&#xff1a;console.log可以打印出来该集合的数据&#xff0c;但是无法获取该集合中的每一个值&#xff0c;打印该集合的length为0&#xff0c;所以也无法遍历该集合进行操…

优先队列——斜堆

【0】README 0.1&#xff09;本文部分内容转自  http://www.cnblogs.com/skywang12345/p/3638493.html&#xff0c; 旨在理解 优先队列——斜堆 的基础知识&#xff1b; 0.2&#xff09; for original source code , please visit https://github.com/pacosonTang/dataStruc…

Class的getResource与ClassLoader的getResource路径/问题

一、Class的getResource(String path)&#xff1a;URL 1、path 不以’/开头时&#xff0c;默认是从此类所在的包下取资源&#xff1b; 2、path 以’/开头时&#xff0c;则是从ClassPath根下获取&#xff1b; System.out.println(Test.class.getResource("")); Syste…

java 轻量级文件数据库_Java:如何创建轻量级数据库微服务

java 轻量级文件数据库基于云的Java数据库应用程序的数量每分钟都在增加。 许多组织部署了数百甚至数千个微服务实例。 但是&#xff0c;相对于运行时环境&#xff0c;大多数应用程序会带来惊人的不必要开销。 反过来&#xff0c;这会使应用程序运行更慢&#xff0c;运行成本更…

html中显示shell脚本的输出,网页从shell脚本中输入并显示结果

首先&#xff0c;不是在BASH脚本中使用$USERNAME。 $USERNAME是一个包含当前用户名的BASH变量。实际上&#xff0c;在BASH中使用UPPERCASE变量通常是一个糟糕的主意。大多数BASH环境变量都是大写字母&#xff0c;可能会导致混淆。让你的变量小写是个好习惯。此外&#xff0c;因…

优先队列——二项队列(binominal queue)

【0】README 0.1&#xff09; 本文文字描述部分转自 数据结构与算法分析&#xff0c; 旨在理解 优先队列——二项队列&#xff08;binominal queue&#xff09; 的基础知识&#xff1b; 0.2&#xff09; 本文核心的剖析思路均为原创&#xff08;insert&#xff0c;merge和del…

Class的getName、getSimpleName与getCanonicalName的区别

一、getName 除了数组外&#xff0c;其他的类都是输出类全名以 String 的形式返回此 Class 对象所表示的实体&#xff08;类、接口、数组类、基本类型或 void&#xff09;名称。 1、此类对象表示的是非数组类型的引用类型&#xff0c; 返回该类的二进制名称&#xff0c;Java…

apache.camel_Apache Camel 3.1 –即将推出更多骆驼核心优化

apache.camel希望一切都很好&#xff0c;您可以安全进入2020年。 Camel团队已经在忙于开发下一个Camel 3.1版本。 目标之一是继续优化骆驼核心&#xff0c;这一次我们花了一些时间来寻找路由引擎中的一些热点。 我们所研究的方面之一也是在Camel路由的每个消息中发生的对象分…

xp系统的计算机管理中用户在哪里,WINDOWSXP的用户管理和系统安全设置

台计算机)⑤回到“添加独立管理单元”对话框&#xff0c;单击“关闭”&#xff0c;回到““控制台->添加/删除管理单元”对话框&#xff0c;再单击“确定”&#xff1b;⑥此时&#xff0c;在控制台窗口左窗格中看到新添加的控制单元“本地计算机策略”&#xff1b;⑦依次展开…