• 关于

    java 9字节的0

    的搜索结果

回答

Java语言概述 **什么是Java语言? ** Java语言是美国Sun公司(Stanford University Network),在1995年推出的高级的编程语言。所谓编程语言,是 计算机的语言,人们可以使用编程语言对计算机下达命令,让计算机完成人们需要的功能。 **Java语言发展历史 ** 1995年Sun公司发布Java1.0版本 1997年发布Java 1.1版本1998年发布Java 1.2版本2000年发布Java 1.3版本2002年发布Java 1.4版本2004年发布Java 1.5版本2006年发布Java 1.6版本2009年Oracle甲骨文公司收购Sun公司,并于2011发布Java 1.7版本2014年发布Java 1.8版本2017年发布Java 9.0版本 **Java语言能做什么? ** Java语言主要应用在互联网程序的开发领域。常见的互联网程序比如天猫、京东、物流系统、网银系统等,以及服 务器后台处理大数据的存储、查询、数据挖掘等也有很多应用。 Java语言开发环境概述 **Java虚拟机——JVM ** JVM(Java Virtual Machine ):Java虚拟机,简称JVM,是运行所有Java程序的假想计算机,是Java程序的 运行环境,是Java 具吸引力的特性之一。我们编写的Java代码,都运行在 JVM 之上。 跨平台:任何软件的运行,都必须要运行在操作系统之上,而我们用Java编写的软件可以运行在任何的操作系 统上,这个特性称为Java语言的跨平台特性。该特性是由JVM实现的,我们编写的程序运行在JVM上,而JVM 运行在操作系统上。 ** JRE 和 JDK ** **JRE ** (Java Runtime Environment) :是Java程序的运行时环境,包含 JVM 和运行时所需要的 核心类库 。 ** JDK ** (Java Development Kit):是Java程序开发工具包,包含 JRE 和开发人员使用的工具。 我们想要运行一个已有的Java程序,那么只需安装 JRE 即可。我们想要开发一个全新的Java程序,那么必须安装 JDK 。 小贴士: 三者关系: JDK > JRE > JVM 数据类型 ** 数据类型分类 ** Java的数据类型分为两大类: - 基本数据类型:包括 整数 、 浮点数 、 字符 、 布尔 。 - 引用数据类型:包括 类 、 数组 、 接口 。 基本数据类型 数据类型关键字内存占用取值范围字节型byte1个字节-128~127短整型short2个字节-32768~32767整型int4个字节-231次方~2的31次方-1长整型long8个字节-2的63次方~2的63次方-1单精度浮点型float4个字节1.4013E-45~3.4028E+38双精度浮点型double8个字节4.9E-324~1.7977E+308字符型char2个字节0-65535布尔类型boolean1个字节true/false Java中的默认类型:整数类型是 int 、浮点类型是 double 。

剑曼红尘 2020-03-30 09:46:23 0 浏览量 回答数 0

回答

我们在《深入分析Java的编译原理》中提到过,为了让Java语言具有良好的跨平台能力,Java独具匠心的提供了一种可以在所有平台上都能使用的一种中间代码——字节码(ByteCode)。 有了字节码,无论是哪种平台(如Windows、Linux等),只要安装了虚拟机,都可以直接运行字节码。 同样,有了字节码,也解除了Java虚拟机和Java语言之间的耦合。这话可能很多人不理解,Java虚拟机不就是运行Java语言的么?这种解耦指的是什么? 其实,目前Java虚拟机已经可以支持很多除Java语言以外的语言了,如Kotlin、Groovy、JRuby、Jython、Scala等。之所以可以支持,就是因为这些语言也可以被编译成字节码。而虚拟机并不关心字节码是有哪种语言编译而来的。 经常使用IDE的开发者可能会发现,当我们在Intelij IDEA中,鼠标右键想要创建Java类的时候,IDE还会提示创建其他类型的文件,这就是IDE默认支持的一些可以运行在JVM上面的语言,没有提示的,可以通过插件来支持。 目前,可以直接在JVM上运行的语言有很多,今天介绍其中比较重要的九种。每种语言通过一段『HelloWorld』代码进行演示,看看不同语言的语法有何不同。 Kotlin Kotlin是一种在Java虚拟机上运行的静态类型编程语言,它也可以被编译成为JavaScript源代码。Kotlin的设计初衷就是用来生产高性能要求的程序的,所以运行起来和Java也是不相上下。Kotlin可以从 JetBrains InteilliJ Idea IDE这个开发工具以插件形式使用。 Hello World In Kotlin fun main(args: Array<String>) { println("Hello, world!") } Groovy Apache的Groovy是Java平台上设计的面向对象编程语言。它的语法风格与Java很像,Java程序员能够很快的熟练使用 Groovy,实际上,Groovy编译器是可以接受完全纯粹的Java语法格式的。 使用Groovy的一个重要特点就是使用类型推断,即能够让编译器能够在程序员没有明确说明的时候推断出变量的类型。Groovy可以使用其他Java语言编写的库。Groovy的语法与Java非常相似,大多数Java代码也匹配Groovy的语法规则,尽管可能语义不同。 Hello World In Groovy static void main(String[] args) { println('Hello, world!'); } Scala Scala是一门多范式的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。 Scala经常被我们描述为多模式的编程语言,因为它混合了来自很多编程语言的元素的特征。但无论如何它本质上还是一个纯粹的面向对象语言。它相比传统编 程语言最大的优势就是提供了很好并行编程基础框架措施了。Scala代码能很好的被优化成字节码,运行起来和原生Java一样快。 Hello World In Scala object HelloWorld { def main(args: Array[String]) { System.out.println("Hello, world!"); } } Jruby JRuby是用来桥接Java与Ruby的,它是使用比Groovy更加简短的语法来编写代码,能够让每行代码执行更多的任务。就和Ruby一样,JRuby不仅仅只提供了高级的语法格式。它同样提供了纯粹的面向对象的实现,闭包等等,而且JRuby跟Ruby自身相比多了很多基于Java类库 可以调用,虽然Ruby也有很多类库,但是在数量以及广泛性上是无法跟Java标准类库相比的。 Hello World In Jruby puts 'Hello, world!' Jython Jython,是一个用Java语言写的Python解释器。Jython能够用Python语言来高效生成动态编译的Java字节码。 Hello World In Jython print "Hello, world!" Fantom Fantom是一种通用的面向对象编程语言,由Brian和Andy Frank创建,运行在Java Runtime Environment,JavaScript和.NET Common Language Runtime上。其主要设计目标是提供标准库API,以抽象出代码是否最终将在JRE或CLR上运行的问题。 Fantom是与Groovy以及JRuby差不多的一样面向对 象的编程语言,但是悲剧的是Fantom无法使用Java类库,而是使用它自己扩展的类库。 Hello World In Fantom class Hello { static Void main() { echo("Hello, world!") } } Clojure Clojure是Lisp编程语言在Java平台上的现代、函数式及动态方言。 与其他Lisp一样,Clojure视代码为数据且拥有一套Lisp宏系统。 虽然Clojure也能被直接编译成Java字节码,但是无法使用动态语言特性以及直 接调用Java类库。与其他的JVM脚本语言不一样,Clojure并不算是面向对象的。 Hello World In Clojure (defn -main [& args] (println "Hello, World!")) Rhino Rhino是一个完全以Java编写的JavaScript引擎,目前由Mozilla基金会所管理。 Rhino的特点是为JavaScript加了个壳,然后嵌入到Java中,这样能够让Java程序员直接使用。其中Rhino的JavaAdapters能够让JavaScript通过调用Java的类来实现特定的功能。 Hello World In Rhino print('Hello, world!') Ceylon Ceylon是一种面向对象,强烈静态类型的编程语言,强调不变性,由Red Hat创建。 Ceylon程序在Java虚拟机上运行,​​可以编译为JavaScript。 语言设计侧重于源代码可读性,可预测性,可扩展性,模块性和元编程性。 Hello World In Ceylon shared void run() { print("Hello, world!"); } 总结 好啦,以上就是目前主流的可以在JVM上面运行的9种语言。加上Java正好10种。如果你是一个Java开发,那么有必要掌握以上9中的一种,这样可以在一些有特殊需求的场景中有更多的选择。推荐在Groovy、Scala、Kotlin中选一个。

montos 2020-06-01 17:04:25 0 浏览量 回答数 0

问题

查找低填充率 结束语:报错

kun坤 2020-06-14 09:44:00 0 浏览量 回答数 0

阿里云高校特惠,助力学生创业梦!0元体验,快速入门云计算!

学生动手场景应用,快速了解并掌握云服务器的各种新奇玩法!

问题

Java基础测试题|挑战你的底线

游客pklijor6gytpx 2019-12-01 22:01:00 2559 浏览量 回答数 3

问题

如何使用Java API在HBase中解码表情符号(unicode)?

游客ufivfoddcd53c 2020-01-04 19:24:32 0 浏览量 回答数 1

回答

距离 Java 11 的正式发布已过去一个多月,而 Java 12 也正在赶来的路上。根据此前开源中国发起的一项关于开发者使用的 Java 版本的调查(https://www.oschina.net/question/2918182_2287320)显示,Java 8 仍然是开发者的主流选择,而 Java 11 是 Java 8 之后的首个 LTS 版本,所以有不少开发者表示会选择升级至 Java 11。按照 Java 的发布计划,Java 12 将于明年 3 月推出,那么问题来了,我们是应该采用 Java 12,还是坚持使用 Java 11 呢? 可能你会觉得这是一个无关紧要的问题,但对于那些需要在 JVM 中使用 Java 的开发者,或是比较看重 Java 新特性的开发者,这是一项十分重要的决策。这篇文章将和大家就这个问题进行相关的分析。 Java 发布计划 现在每六个月就会发布一个新的 Java 版本,所以尽管 Java 11 才发布不久,但距离 Java 12 的发布也就剩下不到五个月的时间。作为发布计划的一部分,某些版本会被指定为长期支持版本(LTS),它们会获得四年或更长时间的技术支持和安全补丁。所以这些版本通常会被称为“主要版本” —— 不是因为它们拥有更多的功能特性,而是因为它们具有长期的技术支持。 预计 Java 11 的更新补丁(11.0.1, 11.0.2, 11.0.3 等)将比 Java 8 的补丁(8u20, 8u40, 8u60)更小更简单。因为 Java 11 的更新将更加集中在安全补丁上,不会像 Java 8 的更新那样带来内部的功能增强。因为 Oracle 希望将 Java 12, 13, 14 等这些版本当做是小更新版本,类比成 Java 8 的话,即是 Java 11u20, 11u40。 Oracle 高级员工一再认为像 8u20 和 8u40 这样的更新常常会带来破坏性的变更,但本文作者表示这不是自己的经历,他记得的唯一有破坏性的变化是为 Javadoc 添加了 --allow-script-in-comments,但它也不是 Java 的核心部分。因此,他从不担心升级到最新版本带来的影响 —— 因为这是 Java 平台的核心优势。 下面深入了解一下为什么在旧的发布模式下,升级版本不会导致任何问题。先看一下新旧发布模式之间的差异: Oracle 的官方观点认为:与 Java 7->8->9 相比,Java 9->10->11的升级和 8->8u20->8u40 更相似。 表格清楚地显示新模式下的 Java 版本发布都会包含许多变更,包括语言变更和 JVM 变更,这两者都会对 IDE、字节码库和框架产生重大影响。此外,不仅会新增其他 API,还会有 API 被删除(这在 Java 8 之前没有发生过)。 Oracle 的观点是,因为每个版本仅在前一个版本发布后的 6 个月推出,所以不会有太多新的“东西”,因此升级并不困难。虽然如此,但这不是重点。重要的是升级是否有可能会破坏代码。很明显,从 11 -> 12 -> 13 开始,代码遭受破坏的可能性要大于 8 -> 8u20 -> 8u40。 11 -> 12 -> 13 与 8u20 -> 8u40 等这样的更新主要区别在于对字节码版本的更改以及对规范的更改,对字节码版本的更改往往特别具有破坏性,大多数框架都大量使用与每个字节码版本密切相关的 ASM 或 ByteBuddy 等库。而 8u20 -> 8u40 仍然使用相同的 Java SE 规范,具有所有相同的类和方法,不同于从 Java 12 移动到 13。 除此之外,Oracle 的另一个声明也十分值得我们关注。声明透露出的消息是,如果坚持使用 Java 11 并计划在下一个 LTS 版本(即 Java 17)发布时再进行升级,开发者可能会发现自己的项目代码无法通过编译。所以请记住,Java 新的开发规则现在声明可以在一个版本中弃用某个 API 方法,并在下一个版本中删除它。 采用新版本 Java 的注意事项 在本节中,将概述在采用新版本 Java 之前必须考虑的一些注意事项/风险。 被新版本系列“绑定” 如果采用了 Java 12 并使用新的语言特性或新的 API,这意味着实际上你已将项目绑定到 Java 的新版本系列。接下来你必须采用 Java 13, 14, 15, 16 和 17,并且必须在下一个版本发布后的一个月内采用每个新版本。 使用了新版本,每个版本的使用寿命为六个月,并且在发布后仅七个月就过时了。这是因为每个版本只有在六个月内提供安全补丁,发布后1个月的第一个补丁和发布后4个月的第二个补丁。7个月后,下一组安全补丁会发布,但旧版本不能获取更新。 因此,你要判断自身的开发流程是否允许升级 Java 版本,时间窗口方面会不会太狭窄? 升级的“绊脚石” 实际使用中有很多阻止我们升级 Java 的因素,下面列出一些常见的: 开发资源不足:你的团队可能会非常忙碌或规模太小,你能保证两年后从 Java 15 升级到 16 的开发时间吗? 构建工具和 IDE:你使用的 IDE 是否会在发布当天支持每个新版本?Maven? Gradle 呢? 如果不是,你有后备计划吗?请记住,你只有1个月的时间来完成升级、测试并将其发布到生产环境中。此外还包括 Checkstyle,JaCoCo,PMD,SpotBugs 等等其他工具。 依赖关系:你的依赖关系是否都准备好用于每个新版本?请记住,它不仅仅是直接依赖项,而是技术堆栈中的所有内容。字节码操作库尤其受到影响,例如 ByteBuddy 和 ASM。 框架:这是另一种依赖,但是一个大而重要的依赖。在一个月的狭窄时间窗口内,Spring 会每六个月发布一个新版本吗? Jakarta EE(以前的 Java EE)会吗?如果它们不这样做会怎么样? 云 / 托管 / 部署 你是否可以控制代码在生产环境中的运行位置和方式?例如,如果你在 AWS Lambda 中运行代码,则无法控制。AWS Lambda 没有采用 Java 9或10,甚至没有采用 Java 11。所以除非 AWS 提供公共保证以支持每个新的 Java 版本,否则根本无法采用 Java 12。 如何托管你的 CI 系统?Jenkins, Travis, Circle, Shippable, GitLab 会快速更新吗?如果不是,你会怎么做? 对未来的预测 如果已经阅读了上面的列表,并且你的代码和流程可以应对。这十分好,但更重要的是要明白,你也在限制未来进行改变的能力。例如,你的代码可能今天不在 AWS Lambda 上运行,但未来三年呢? 为采用新版本进行规划 如果正在考虑采用新版本的 Java,建议你准备一份现在所依赖的所有内容的清单,或者可能在未来3年内会依赖的。你需要保证该列表中的所有内容都能正常工作,并与新版本一起升级,或者如果该依赖项不再更新,请制定好计划。作者提供了他的清单: Amazon AWS Eclipse IntelliJ Travis CI Shippable CI Maven Maven plugins (compile, jar, source, javadoc, etc) Checkstyle, 以及相关的 IDE 插件和 maven 插件 JaCoCo, 以及相关的 IDE 插件和 maven 插件 PMD 和相关的 maven 插件 SpotBugs 和相关的 maven 插件 OSGi bundle metadata tool Bytecode 工具(Byte buddy / ASM etc) 超过 100 个 jar 包依赖项 说了这么多,作者当然不是鼓励大家不进行升级,新语言特性带来的好处以及性能增强会让开发者受益,但升级背后的风险也应该考虑进去。 其他第三方产商的声明 Spring 框架已经在视频中表达了对 Java 12 的策略。关键部分是: “Java 8 和 11 作为 LTS 版本会持续获得我们的正式支持,对于过渡版本,我们也会尽最大努力支持。如果你升级到 Java 11,我们非常愿意和你合作,但它们不会获得正式的生产环境支持。因为长期支持版本才是我们关注的重心,对于 Java 12 及更高版本我们会尽最大的努力。” 作为典型软件供应商的一个例子,Liferay 声明如下: Liferay 已决定不会对 JDK 的每个主要版本进行认证。我们将选择遵循 Oracle 的主导并仅认证标记为 LTS 的版本。—— Liferay 博客 640?wx_fmt=png 总结 相信肯定已经有开发团队采用了新版本的 Java,但希望他们是经过思考判断之后做出的决定。除了文章中提到的问题,还会有很多其他在升级前需要思考的因素,欢迎在评论中留下你的看法。

问问小秘 2020-04-29 17:45:51 0 浏览量 回答数 0

回答

Java中的整型主要包含byte、short、int和long这四种,表示的数字范围也是从小到大的,之所以表示范围不同主要和他们存储数据时所占的字节数有关。 先来个简答的科普,1字节=8位(bit)。java中的整型属于有符号数。 先来看计算中8bit可以表示的数字: 最小值:10000000 (-128)(-2^7) 最大值:01111111(127)(2^7-1) 具体计算方式参考:Java中,为什么byte类型的取值范围为-128~127? - CSDN博客 整型的这几个类型中,   byte:byte用1个字节来存储,范围为-128(-2^7)到127(2^7-1),在变量初始化的时候,byte类型的默认值为0。   short:short用2个字节存储,范围为-32,768 (-2^15)到32,767 (2^15-1),在变量初始化的时候,short类型的默认值为0,一般情况下,因为Java本身转型的原因,可以直接写为0。   int:int用4个字节存储,范围为-2,147,483,648 (-2^31)到2,147,483,647 (2^31-1),在变量初始化的时候,int类型的默认值为0。   long:long用8个字节存储,范围为-9,223,372,036,854,775,808 (-2^63)到9,223,372,036, 854,775,807 (2^63-1),在变量初始化的时候,long类型的默认值为0L或0l,也可直接写为0。 上面说过了,整型中,每个类型都有一定的表示范围,但是,在程序中有些计算会导致超出表示范围,即溢出。如以下代码: int i = Integer.MAX_VALUE; int j = Integer.MAX_VALUE; int k = i + j; System.out.println("i (" + i + ") + j (" + j + ") = k (" + k + ")"); 输出结果:i (2147483647) + j (2147483647) = k (-2) 这就是发生了溢出,溢出的时候并不会抛异常,也没有任何提示。所以,在程序中,使用同类型的数据进行运算的时候,一定要注意数据溢出的问题。

montos 2020-06-01 16:00:31 0 浏览量 回答数 0

回答

这恰好是您期望的X9.63兼容签名的大小,该签名由两个有符号大端整数的DER编码组成。如果要具有64字节的签名,则应使用[以下说明] (https://crypto.stackexchange.com/a/60011/1172)在内部转换2个整数。在I2OSP和OS2IP对Java的实现,可以发现在这里。 因此,步骤如下: 解析ASN.1签名;BigInteger使用new BigInteger(byte[])构造函数转换为值;使用I2OSP创建r和s值作为字节数组(32个八位字节的输出大小);将r和s连接起来以创建64字节的签名。 回答来源:Stack Overflow

montos 2020-03-26 14:03:49 0 浏览量 回答数 0

回答

杨晓峰:在可预见的将来,Java 依旧是企业软件、大数据、电商等等最核心的技术栈。但是目前 Java/JVM 能力在云时代有一定局限性,比如云里强调的无服务器、微服务等场景,Java/JVM 都有一定短板。 另外 Java 新版本采用速度这么慢,本身就说明,Java 创新和实际需求存在某种程度的脱节——一方面大量创新会带来兼容性和版本混乱的问题;另外创新带来的优点却需要极大增大开发运维成本,这也让部分创新的价值被抵消了。 但是 Java 会被取代吗?应该也不会,目前在社区、工具、类库等等方面,Java 还没有真正意义的对手,但是最大的威胁是新的需求浪潮是否与你有关。我们可以看下 GitHub 上 Java 新项目的趋势,一定程度上可以佐证 Java 坚实的基本面和不可忽视的隐忧。 阿里巴巴李三红:从技术角度来看,Java(JDK)这二十几年的发展一直试图在 Productivity 以及 Performance 之间做最好的平衡。Java 是静态类型语言,但是为了生产效率提供了大量动态的特性比如 Bytecode Instrument、Dynamic Class Loading、Metaprogramming(Annotation、Reflection 等 ,这些形成了 Java 在运维、生产监控等领域的基石技术。 同时由于 Java 大量的动态特性存在,使得它在面向云原生、Serverless 计算时 Memory Footprint、Startup 方面被人所诟病。这也是整个 Java 社区,当然包括 Alibaba Dragonwell 所试图解决的问题。 阿里巴巴小马哥:Java 目前仍具在编程语言排⾏榜上夺魁的能力,不过在整体比重上微幅下滑。个⼈看来,未来这个趋势还将持续。究其原因,一⽅⾯是由于新语种出现的中短期效应,一方面是 Java 的编程复杂度并没有明显的降低,比如 I/O 处理、并发 / 并⾏计算,以及类加载等等。再者是 Java 与操作系统之间的交互仍不够充分,尽管 Java 9 开始提供了不少的 API,然⽽了解和使用的群体不⾜。Java 在这方面明显不及 GO 语言。 从语⾔层⾯来看,Java 正在向主流非 Java 语⾔融合,解决其中鸿沟的关键是语法的变化,比如 Java 8 的 Lambda 表达式 和 Java 10 的局部变量类型( var )等。个人认为这是一件好事,未来前后端不分家,相互渗透,对于彼此语言都是良性发展。 除此之外,个人比较期待的是 GraalVM 对 Java 的改变,传统 Java 应用必须依赖 JVM 进程加载字节码后解释执行,无法保证所有的代码能够在运行期编程完成,不免有运⾏时编译所带来的性能开销,从而影响 JVM 的启停时间。简单地说,这种方式不够 Native,对于云原生或许不够友好。如果未来 GraalVM 的社区版也能够像 OpenJDK 那般“亲民”,那么,Java 的变化将是颠覆性的。 美团吴革:当前 Java 已经发展成为一个庞然大物,语言上基本不会有太多突破,更多是借鉴和兼容。随着 GC 算法的升级和编译器换代,面对 Go 等新一代语言挑战,还有一战之力。 腾讯单致豪:毋庸置疑,Java 语言依然活力十足,但在某些方面已经失去优势,如云原生领域现在出现了更具活力的 Go 语言。纷繁的世界必定会出现多语言并存、不断替代的现象。回顾历史发展进程,一种语言要从出现到早期大众使用基本都需要十年时间,能历经十年磨砺生存下来的开发语言,必定是有很强的生命力,而且都会有不同的企业构筑其生态。正如上文所说:不同语言也会在自己优势之处持续发展,形成很强的竞争壁垒。 字节跳动王石冲:Scala 语言目前有两个大的目标运行平台——JVM 和 js,所以 Scala 作为一个语言和生态并不敢完全投资在单一目标平台上。虽然 JVM 本身在不断进步,但是 Java 已经被同平台的多种语言赶超,比如 Kotlin、Clojure、Groovy。

游客pklijor6gytpx 2019-12-02 03:11:40 0 浏览量 回答数 0

回答

分析一下字节码就知道了。 public class collections.StringDemo { // Method descriptor #6 ()V // Stack: 1, Locals: 1 public StringDemo(); 0 aload_0 [this] 1 invokespecial java.lang.Object() [8] 4 return Line numbers: [pc: 0, line: 6] Local variable table: [pc: 0, pc: 5] local: this index: 0 type: collections.StringDemo // Method descriptor #15 ([Ljava/lang/String;)V // Stack: 5, Locals: 4 public static void main(java.lang.String[] args); 0 ldc <String "abc"> [16] 2 astore_1 [str] 3 ldc <String "a"> [18] 5 astore_2 [str2] 6 ldc <String "bc"> [20] 8 astore_3 [str3] 9 getstatic java.lang.System.out : java.io.PrintStream [22] 12 aload_1 [str] 13 new java.lang.StringBuilder [28] 16 dup 17 aload_2 [str2] 18 invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [30] 21 invokespecial java.lang.StringBuilder(java.lang.String) [36] 24 aload_3 [str3] 25 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [39] 28 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [43] 31 if_acmpne 38 34 iconst_1 35 goto 39 38 iconst_0 39 invokevirtual java.io.PrintStream.println(boolean) : void [47] 42 getstatic java.lang.System.out : java.io.PrintStream [22] 45 aload_1 [str] 46 new java.lang.StringBuilder [28] 49 dup 50 ldc <String "a"> [18] 52 invokespecial java.lang.StringBuilder(java.lang.String) [36] 55 aload_3 [str3] 56 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [39] 59 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [43] 62 if_acmpne 69 65 iconst_1 66 goto 70 69 iconst_0 70 invokevirtual java.io.PrintStream.println(boolean) : void [47] 73 getstatic java.lang.System.out : java.io.PrintStream [22] 76 aload_1 [str] 77 ldc <String "abc"> [16] 79 if_acmpne 86 82 iconst_1 83 goto 87 86 iconst_0 87 invokevirtual java.io.PrintStream.println(boolean) : void [47] 90 return Line numbers: [pc: 0, line: 8] [pc: 3, line: 9] [pc: 6, line: 10] [pc: 9, line: 11] [pc: 42, line: 12] [pc: 73, line: 13] [pc: 90, line: 15] Local variable table: [pc: 0, pc: 91] local: args index: 0 type: java.lang.String[] [pc: 3, pc: 91] local: str index: 1 type: java.lang.String [pc: 6, pc: 91] local: str2 index: 2 type: java.lang.String [pc: 9, pc: 91] local: str3 index: 3 type: java.lang.String } 现在一个个的分析:ldc表示将int, float或String型常量值从常量池中推送至栈顶.astore表示将栈顶引用型数值存入指定本地变量 那么表示 abc 在运行时常量池中间取出,并且将引用赋给str变量。 同理,str1,str2都一样。 那么这就说明一个问题: 类似于String str1="dddd"说明"dddd"字符串存在运行时常量池中,而不是存在堆中间。然后看s2+s3:java运算符重载了加法。也就是字符串的加号是通过StringBuilder的append和toString来完成的。查看toString的源码:很显然是新生成了一个String,引用地址不一样,那么"=="判断当然为false。然后看说明,对于这种情况,java编译器做了优化。直接存储在运行时常量池中间。那么当然为true。 那么C#。不知道他们运行机制是咋样的。

蛮大人123 2019-12-02 01:52:19 0 浏览量 回答数 0

问题

【精品问答】Java基础测试题答案

游客pklijor6gytpx 2019-12-01 22:02:11 2957 浏览量 回答数 3

回答

它们是不同的,让我们看一下字节码: 1.版本: L0 LINENUMBER 9 L0 ALOAD 0 ICONST_0 AALOAD INVOKEVIRTUAL java/lang/String.getBytes ()[B ARRAYLENGTH NEWARRAY T_BYTE ASTORE 1 L1 LINENUMBER 10 L1 ALOAD 0 ICONST_0 AALOAD INVOKEVIRTUAL java/lang/String.getBytes ()[B ASTORE 1 L2 LINENUMBER 11 L2 RETURN L3 LOCALVARIABLE args [Ljava/lang/String; L0 L3 0 LOCALVARIABLE bytearr [B L1 L3 1 MAXSTACK = 2 MAXLOCALS = 2 2.版本: L0 LINENUMBER 9 L0 ALOAD 0 ICONST_0 AALOAD INVOKEVIRTUAL java/lang/String.getBytes ()[B ASTORE 1 L1 LINENUMBER 10 L1 RETURN L2 LOCALVARIABLE args [Ljava/lang/String; L0 L2 0 LOCALVARIABLE bytearr [B L1 L2 1 MAXSTACK = 2 MAXLOCALS = 2 区别在于,这些指令来自额外的行: LINENUMBER 9 L0 ALOAD 0 ICONST_0 AALOAD INVOKEVIRTUAL java/lang/String.getBytes ()[B ARRAYLENGTH NEWARRAY T_BYTE ASTORE 1 这引入了额外的开销(getBytes被调用两次,更多指令)。通过调用bytearr = a.getBytes()jvm,已经可以处理要存储的数组的大小。 但是由于第一次初始化是多余的,因此编译器可能会在某个时候(经过足够的运行)对其进行优化。仍然不需要额外的指令和可读性较低的代码。 回答来源:Stack Overflow

montos 2020-03-28 09:38:41 0 浏览量 回答数 0

问题

【精品问答】Java之整体走势及未来发展专场

游客pklijor6gytpx 2019-12-01 21:55:12 36 浏览量 回答数 1

回答

Java基本类型及其包装有哪些? Java基本类型-整数类型byte、short、int和long byte:字节型;short:短整型;int:整型;long:长整型。 刚开始学习时有种疑惑,为啥弄这么多整数类型? 从字节型到长整型,整数的范围总是在不断增加,不够用了自然就要扩展范围,添加新的类型;若范围小的整数浪费空间太多,又会影响程序,所以在使用时就有了类型供我们选择。 Java基本类型-- 浮点型float和double https://developer.aliyun.com/ask/280806 Java基本类型-字符型char Java采用的是Unicode编码格式,字符类型的变量不仅可以接收单字符常量,还可以接收0~65535之间的整数。 转义字符表(有些特殊含义的字符需要通过\来协助) Java基本类型-布尔型boolean Java中的布尔型只表示字面true和false,不同C++之处,如果将一个整数值赋值给布尔类型变量,编译器将报错。 Java基本类型- Java常量默认类型有哪些? 在Java中整型常量默认int类型,如果想要使用long类型常量,需要在常量后添加L/l字符,例如:15L 浮点数默认为double类型,如果想要float类型需要添加F/f,例如:3.14F Java基本类型-- 基本类型的范围包括哪些? 我们可以利用基本类型的包装类中的关键字MAX_VALUE和MIN_VALUE,打印出基本类型的范围。 public class PrintRange { public static void main(String[] args) { System.out.println("byte: "+Byte.MIN_VALUE+" ~ "+Byte.MAX_VALUE); System.out.println("short: "+Short.MIN_VALUE+" ~ "+Short.MAX_VALUE); System.out.println("int: "+Integer.MIN_VALUE+" ~ "+Integer.MAX_VALUE); System.out.println("long: "+Long.MIN_VALUE+" ~ "+Long.MAX_VALUE); System.out.println("float: "+Float.MIN_VALUE+" ~ "+Float.MAX_VALUE); System.out.println("double: "+Double.9+" ~ "+Double.MAX_VALUE); System.out.println("char: "+Character.MIN_VALUE+" ~ "+Character.MAX_VALUE); } } Java基本类型-基本类型间的相互转换- 隐式转换、显式转化 隐式转换 范围小的类型可以自动转换为范围大的类型,大范围类型能容纳小范围类型(也称显示转换为扩展转换)这些转换都是兼容的。 显式转换 大的范围转换为小范围类型,会造成信息丢失(也称隐式转换为窄化转换),不兼容性转换。如图,利用类型转换操作符(cast)进行显示转换。 浮点数转换为整数的小数问题 float和double类型转换为整数时,总是舍去小数点后面的部分,称此行为为截尾。 如果对小数点后面的部分进行四舍五入,即舍入操作,需要利用java.lang.Math中的round()方法 Java基本类型-基本类型和包装类之间的转换- 自动装箱和拆箱 Java5出现的特性,基本类型和封装类之间可以进行自动拆箱和装箱进行类型转换(由基类转换为包装类)。 ** 包装类中还包含很多将包装类装换为其他基类的接口,详细的可以查看Java API文档** java基本类型-- 基本类型和String类型之间的转换 在我们进行Java GUI界面开发时,通常会获取文本输入框的值,这就可能涉及到String类型转换为基本类型的问题。 public class PrintRange { public static void main(String[] args) { //基类转换为String类型 int a = 125; String s = String.valueOf(a); //String类型转换为基类 a = Integer.parseInt(s); } } String转换为基类利用的是基类对应包装类的parse···方法,基类转换字符串用的是String类中的valueOf方法,这些在Java API中都有介绍。 Java基本类型作为方法参数传递中的转换

问问小秘 2020-03-30 14:41:23 0 浏览量 回答数 0

问题

关于MD5加密同一个字符串调用方式不同,返回密文不同。见鬼啦!!!!!? 400 报错

爱吃鱼的程序员 2020-06-03 15:05:59 1 浏览量 回答数 1

问题

java文件上传到sqlserver数据库的问题:报错

kun坤 2020-06-06 22:39:11 0 浏览量 回答数 1

问题

如何在Java中初始化字节数组?

保持可爱mmm 2020-02-07 01:18:05 1 浏览量 回答数 1

回答

我感觉重点是思维,多考虑程序的安全性,接收数据注意过滤,数据库连接防注入,用什么语言其实差不多。######这个需要多写,非一朝一夕可矣。######书山有路勤为径 ###### 你是写java,不适应php,变量不声明,数据结构可以随意定制,方式。还是多加上校验,刚开始烦点,写多了就习惯了。 还有了就是多看php的api,不能看着php函数名子就直接使用,好多坑的。 如count函数,参数是数组时,当然返回数组长度。 如果参数是字符串,返回便是字符串长度。 如有有人写个方法取数组里第几个参数时, 调用人没注意,传个字符串就完蛋了。(之前有个同事定义这样一个函数 取数据第一个值,删除数据库中指定的公司账号,有个A货同事,调用传一个字符串 '91',把 公司为9的账号给删除了) 完全不是一个意思,但它不报错。 遇到数据没了找都很能找着原因。 ######回复 @zonghua : 对的。 我因该说count 字符串返回的是字节长度######PHP的字符串长度是字节,而java真的是字符的数目

kun坤 2020-06-09 11:45:05 0 浏览量 回答数 0

问题

java读取文本超级大问题:报错

kun坤 2020-06-07 17:10:01 0 浏览量 回答数 1

问题

关于多线程编程您不知道的 5 件事:报错

kun坤 2020-06-07 21:21:26 0 浏览量 回答数 1

问题

Linux下忘记MySQL的root密码的解决方案,数据库报错

python小菜菜 2020-06-01 19:35:36 0 浏览量 回答数 1

回答

本文主要介绍Java中的自动拆箱与自动装箱的有关知识。 基本数据类型 基本类型,或者叫做内置类型,是Java中不同于类(Class)的特殊类型。它们是我们编程中使用最频繁的类型。 Java是一种强类型语言,第一次申明变量必须说明数据类型,第一次变量赋值称为变量的初始化。 Java基本类型共有八种,基本类型可以分为三类: 字符类型char 布尔类型boolean 数值类型byte、short、int、long、float、double。 数值类型又可以分为整数类型byte、short、int、long和浮点数类型float、double。 Java中的数值类型不存在无符号的,它们的取值范围是固定的,不会随着机器硬件环境或者操作系统的改变而改变。 实际上,Java中还存在另外一种基本类型void,它也有对应的包装类 java.lang.Void,不过我们无法直接对它们进行操作。 基本数据类型有什么好处 我们都知道在Java语言中,new一个对象是存储在堆里的,我们通过栈中的引用来使用这些对象;所以,对象本身来说是比较消耗资源的。 对于经常用到的类型,如int等,如果我们每次使用这种变量的时候都需要new一个Java对象的话,就会比较笨重。所以,和C++一样,Java提供了基本数据类型,这种数据的变量不需要使用new创建,他们不会在堆上创建,而是直接在栈内存中存储,因此会更加高效。 整型的取值范围 Java中的整型主要包含byte、short、int和long这四种,表示的数字范围也是从小到大的,之所以表示范围不同主要和他们存储数据时所占的字节数有关。 先来个简答的科普,1字节=8位(bit)。java中的整型属于有符号数。 先来看计算中8bit可以表示的数字: 最小值:10000000 (-128)(-2^7) 最大值:01111111(127)(2^7-1) 整型的这几个类型中, byte:byte用1个字节来存储,范围为-128(-2^7)到127(2^7-1),在变量初始化的时候,byte类型的默认值为0。 short:short用2个字节存储,范围为-32,768 (-2^15)到32,767 (2^15-1),在变量初始化的时候,short类型的默认值为0,一般情况下,因为Java本身转型的原因,可以直接写为0。 int:int用4个字节存储,范围为-2,147,483,648 (-2^31)到2,147,483,647 (2^31-1),在变量初始化的时候,int类型的默认值为0。 long:long用8个字节存储,范围为-9,223,372,036,854,775,808 (-2^63)到9,223,372,036, 854,775,807 (2^63-1),在变量初始化的时候,long类型的默认值为0L或0l,也可直接写为0。 超出范围怎么办 上面说过了,整型中,每个类型都有一定的表示范围,但是,在程序中有些计算会导致超出表示范围,即溢出。如以下代码: int i = Integer.MAX_VALUE; int j = Integer.MAX_VALUE; int k = i + j; System.out.println("i (" + i + ") + j (" + j + ") = k (" + k + ")"); 输出结果:i (2147483647) + j (2147483647) = k (-2) **这就是发生了溢出,溢出的时候并不会抛异常,也没有任何提示。**所以,在程序中,使用同类型的数据进行运算的时候,一定要注意数据溢出的问题。 包装类型 Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。 包装类均位于java.lang包,包装类和基本数据类型的对应关系如下表所示 基本数据类型包装类byteBytebooleanBooleanshortShortcharCharacterintIntegerlongLongfloatFloatdoubleDouble 在这八个类名中,除了Integer和Character类以后,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写即可。 为什么需要包装类 很多人会有疑问,既然Java中为了提高效率,提供了八种基本数据类型,为什么还要提供包装类呢? 这个问题,其实前面已经有了答案,因为Java是一种面向对象语言,很多地方都需要使用对象而不是基本数据类型。比如,在集合类中,我们是无法将int 、double等类型放进去的。因为集合的容器要求元素是Object类型。 为了让基本类型也具有对象的特征,就出现了包装类型,它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,丰富了基本类型的操作。 拆箱与装箱 那么,有了基本数据类型和包装类,肯定有些时候要在他们之间进行转换。比如把一个基本数据类型的int转换成一个包装类型的Integer对象。 我们认为包装类是对基本类型的包装,所以,把基本数据类型转换成包装类的过程就是打包装,英文对应于boxing,中文翻译为装箱。 反之,把包装类转换成基本数据类型的过程就是拆包装,英文对应于unboxing,中文翻译为拆箱。 在Java SE5之前,要进行装箱,可以通过以下代码: Integer i = new Integer(10); 自动拆箱与自动装箱 在Java SE5中,为了减少开发人员的工作,Java提供了自动拆箱与自动装箱功能。 自动装箱: 就是将基本数据类型自动转换成对应的包装类。 自动拆箱:就是将包装类自动转换成对应的基本数据类型。 Integer i =10; //自动装箱 int b= i; //自动拆箱 Integer i=10 可以替代 Integer i = new Integer(10);,这就是因为Java帮我们提供了自动装箱的功能,不需要开发者手动去new一个Integer对象。 自动装箱与自动拆箱的实现原理 既然Java提供了自动拆装箱的能力,那么,我们就来看一下,到底是什么原理,Java是如何实现的自动拆装箱功能。 我们有以下自动拆装箱的代码: public static void main(String[]args){ Integer integer=1; //装箱 int i=integer; //拆箱 } 对以上代码进行反编译后可以得到以下代码: public static void main(String[]args){ Integer integer=Integer.valueOf(1); int i=integer.intValue(); } 从上面反编译后的代码可以看出,int的自动装箱都是通过Integer.valueOf()方法来实现的,Integer的自动拆箱都是通过integer.intValue来实现的。如果读者感兴趣,可以试着将八种类型都反编译一遍 ,你会发现以下规律: 自动装箱都是通过包装类的valueOf()方法来实现的.自动拆箱都是通过包装类对象的xxxValue()来实现的。 哪些地方会自动拆装箱 我们了解过原理之后,在来看一下,什么情况下,Java会帮我们进行自动拆装箱。前面提到的变量的初始化和赋值的场景就不介绍了,那是最简单的也最容易理解的。 我们主要来看一下,那些可能被忽略的场景。 场景一、将基本数据类型放入集合类 我们知道,Java中的集合类只能接收对象类型,那么以下代码为什么会不报错呢? List<Integer> li = new ArrayList<>(); for (int i = 1; i < 50; i ++){ li.add(i); } 将上面代码进行反编译,可以得到以下代码: List<Integer> li = new ArrayList<>(); for (int i = 1; i < 50; i += 2){ li.add(Integer.valueOf(i)); } 以上,我们可以得出结论,当我们把基本数据类型放入集合类中的时候,会进行自动装箱。 场景二、包装类型和基本类型的大小比较 有没有人想过,当我们对Integer对象与基本类型进行大小比较的时候,实际上比较的是什么内容呢?看以下代码: Integer a=1; System.out.println(a==1?"等于":"不等于"); Boolean bool=false; System.out.println(bool?"真":"假"); 对以上代码进行反编译,得到以下代码: Integer a=1; System.out.println(a.intValue()==1?"等于":"不等于"); Boolean bool=false; System.out.println(bool.booleanValue?"真":"假"); 可以看到,包装类与基本数据类型进行比较运算,是先将包装类进行拆箱成基本数据类型,然后进行比较的。 场景三、包装类型的运算 有没有人想过,当我们对Integer对象进行四则运算的时候,是如何进行的呢?看以下代码: Integer i = 10; Integer j = 20; System.out.println(i+j); 反编译后代码如下: Integer i = Integer.valueOf(10); Integer j = Integer.valueOf(20); System.out.println(i.intValue() + j.intValue()); 我们发现,两个包装类型之间的运算,会被自动拆箱成基本类型进行。 场景四、三目运算符的使用 这是很多人不知道的一个场景,作者也是一次线上的血淋淋的Bug发生后才了解到的一种案例。看一个简单的三目运算符的代码: boolean flag = true; Integer i = 0; int j = 1; int k = flag ? i : j; 很多人不知道,其实在int k = flag ? i : j;这一行,会发生自动拆箱。反编译后代码如下: boolean flag = true; Integer i = Integer.valueOf(0); int j = 1; int k = flag ? i.intValue() : j; System.out.println(k); 这其实是三目运算符的语法规范。当第二,第三位操作数分别为基本类型和对象时,其中的对象就会拆箱为基本类型进行操作。 因为例子中,flag ? i : j;片段中,第二段的i是一个包装类型的对象,而第三段的j是一个基本类型,所以会对包装类进行自动拆箱。如果这个时候i的值为null,那么就会发生NPE。(自动拆箱导致空指针异常) 场景五、函数参数与返回值 这个比较容易理解,直接上代码了: //自动拆箱 public int getNum1(Integer num) { return num; } //自动装箱 public Integer getNum2(int num) { return num; } 自动拆装箱与缓存 Java SE的自动拆装箱还提供了一个和缓存有关的功能,我们先来看以下代码,猜测一下输出结果: public static void main(String... strings) { Integer integer1 = 3; Integer integer2 = 3; if (integer1 == integer2) System.out.println("integer1 == integer2"); else System.out.println("integer1 != integer2"); Integer integer3 = 300; Integer integer4 = 300; if (integer3 == integer4) System.out.println("integer3 == integer4"); else System.out.println("integer3 != integer4"); } 我们普遍认为上面的两个判断的结果都是false。虽然比较的值是相等的,但是由于比较的是对象,而对象的引用不一样,所以会认为两个if判断都是false的。在Java中,==比较的是对象应用,而equals比较的是值。所以,在这个例子中,不同的对象有不同的引用,所以在进行比较的时候都将返回false。奇怪的是,这里两个类似的if条件判断返回不同的布尔值。 上面这段代码真正的输出结果: integer1 == integer2 integer3 != integer4 原因就和Integer中的缓存机制有关。在Java 5中,在Integer的操作上引入了一个新功能来节省内存和提高性能。整型对象通过使用相同的对象引用实现了缓存和重用。 适用于整数值区间-128 至 +127。 只适用于自动装箱。使用构造函数创建对象不适用。 具体的代码实现可以阅读Java中整型的缓存机制一文,这里不再阐述。 我们只需要知道,当需要进行自动装箱时,如果数字在-128至127之间时,会直接使用缓存中的对象,而不是重新创建一个对象。 其中的javadoc详细的说明了缓存支持-128到127之间的自动装箱过程。最大值127可以通过-XX:AutoBoxCacheMax=size修改。 实际上这个功能在Java 5中引入的时候,范围是固定的-128 至 +127。后来在Java 6中,可以通过java.lang.Integer.IntegerCache.high设置最大值。 这使我们可以根据应用程序的实际情况灵活地调整来提高性能。到底是什么原因选择这个-128到127范围呢?因为这个范围的数字是最被广泛使用的。 在程序中,第一次使用Integer的时候也需要一定的额外时间来初始化这个缓存。 在Boxing Conversion部分的Java语言规范(JLS)规定如下: 如果一个变量p的值是: -128至127之间的整数(§3.10.1) true 和 false的布尔值 (§3.10.3) ‘\u0000’至 ‘\u007f’之间的字符(§3.10.4) 范围内的时,将p包装成a和b两个对象时,可以直接使用a==b判断a和b的值是否相等。 自动拆装箱带来的问题 当然,自动拆装箱是一个很好的功能,大大节省了开发人员的精力,不再需要关心到底什么时候需要拆装箱。但是,他也会引入一些问题。 包装对象的数值比较,不能简单的使用==,虽然-128到127之间的数字可以,但是这个范围之外还是需要使用equals比较。 前面提到,有些场景会进行自动拆装箱,同时也说过,由于自动拆箱,如果包装类对象为null,那么自动拆箱时就有可能抛出NPE。 如果一个for循环中有大量拆装箱操作,会浪费很多资源。 参考资料 Java的自动拆装箱

montos 2020-06-01 21:24:01 0 浏览量 回答数 0

回答

一,android串口通信 串口通信采用一个第三方开源项目,实现串口数据收发。 使用了 api和jni; 支持4串口同时收发,有定时自动发送功能,收发模式可选Txt或Hex模式; n,8,1,没得选; 为减轻界面卡顿的情况,接收区的刷新采用单独的线程进行定时刷新; 发送区的数据以及一些设置项,在程序关闭时会自动保存,打开时自动载入; jni使用最新的NDKr8b重新编译了一下 简单编写步骤: 1.新建一个项目,自己起个名字 2.直接复制serialport api和jni文件夹到新建的工程,如果不想自己编译jni,就连libs文件夹也一起复制 3.去android官方网站下载NDK,解压,在CMD中转到jni目录,并执行 绝对路径ndk-build 4.自己再封装一个工具类或直接使用SerialPort类都行,举个直接使用的例: 直接剽窃原项目的SerialPortActivity.java,并稍微改一下,重点改这里 mSerialPort = mApplication.getSerialPort(); 这里可以改成 new SerialPort(new File("/dev/s3c2410_serial0"), 9600, 0);//COM0,波特率9600 SerialPortFinder的使用就没什么好讲的了,实例化后用.getAllDevicesPath()就能获取到所有设备了。其它如数据转换等请参考源码 源码可以参考谷歌android-serialport-api例子 二,串口通信协议解析 1.通信基本格式 字段 描述 长度(字节) 起始符 0F,十六进制码 1 信息类型 一个字节,十六进制码(0F,F0,FF等保留码不用)1 信息长度 是信息内容的长度,ASCII码表示(0~9,A~F,最大长度为256)(例如长为11个,十六进制是0B,则两个字节就写0x30 0x42)。 注:因为最大长度256不能满足有些指令的要求,所以对长度做了扩展,下面是扩展说明: 如果第一个字节的最高位为1,则表示扩展长度。在扩展长度状态下,其他15个字节通过16进制大端模式来保存长度。比如:0x80 0x12表示长度为0x001 2,0x81 0x12表示长度为0x0112。2 信息内容 一组十六进制码 N 校验 一个字节,十六进制码,是自信息类型起至对象号止所有码的异或。1 结束符 F0,一个字节,十六进制码 (为了保证可靠性,车机下发的结束符为F0 FF)1 2.协议解析 /** * 读取终端设备数据 * @author Administrator */ private class ReadThread extends Thread { @Override public void run() { super.run(); // 定义一个包的最大长度 int maxLength = 2048; byte[] buffer = new byte[maxLength]; // 每次收到实际长度 int available = 0; // 当前已经收到包的总长度 int currentLength = 0; // 协议头长度4个字节(开始符1,类型1,长度2) int headerLength = 4; while (!isInterrupted()) { try { available = mInputStream.available(); if (available > 0) { // 防止超出数组最大长度导致溢出 if (available > maxLength - currentLength) { available = maxLength - currentLength; } mInputStream.read(buffer, currentLength, available); currentLength += available; } } catch (Exception e) { e.printStackTrace(); } int cursor = 0; // 如果当前收到包大于头的长度,则解析当前包 while (currentLength >= headerLength) { // 取到头部第一个字节 if (buffer[cursor] != 0x0F) { --currentLength; ++cursor; continue; } int contentLenght = parseLen(buffer, cursor, headerLength); // 如果内容包的长度大于最大内容长度或者小于等于0,则说明这个包有问题,丢弃 if (contentLenght <= 0 || contentLenght > maxLength - 5) { currentLength = 0; break; } // 如果当前获取到长度小于整个包的长度,则跳出循环等待继续接收数据 int factPackLen = contentLenght + 5; if (currentLength < contentLenght + 5) { break; } // 一个完整包即产生 // proceOnePacket(buffer,i,factPackLen); onDataReceived(buffer, cursor, factPackLen); currentLength -= factPackLen; cursor += factPackLen; } // 残留字节移到缓冲区首 if (currentLength > 0 && cursor > 0) { System.arraycopy(buffer, cursor, buffer, 0, currentLength); } } } } /** * 获取协议内容长度 * @param header * @return */ public int parseLen(byte buffer[], int index, int headerLength) { // if (buffer.length - index < headerLength) { return 0; } byte a = buffer[index + 2]; byte b = buffer[index + 3]; int rlt = 0; if (((a >> 7) & 0x1) == 0x1) { rlt = (((a & 0x7f) << 8) | b); } else { char[] tmp = new char[2]; tmp[0] = (char) a; tmp[1] = (char) b; String s = new String(tmp, 0, 2); rlt = Integer.parseInt(s, 16); } return rlt; } protected void onDataReceived(final byte[] buffer, final int index, final int packlen) { System.out.println("收到信息"); byte[] buf = new byte[packlen]; System.arraycopy(buffer, index, buf, 0, packlen); ProtocolAnalyze.getInstance(myHandler).analyze(buf); }

爵霸 2019-12-02 01:56:32 0 浏览量 回答数 0

回答

enum是jdk5引入的语法糖,定义一个enum类实际上也是定义一个class,只是通过enum定义这个特殊class的时候,编译器会帮你做些事情:1.所有的枚举类会默认继承Enum类2.所有的枚举类是final的,不可扩展子类3.所有定义的枚举常量,会生成定义的枚举类中生成public static final常量所以,枚举类和普通类的用法没有太大的区别,譬如: case1: public enum TrafficLight { RED("红灯"), GREEN("绿灯"), YELLOW("黄灯"), ; private final String desc; TrafficLight (String desc) { this.desc = desc; } public String getDesc() { return desc; } } case2: public enum TrafficLight { RED("红灯") { public TrafficLight next() { return YELLOW; } }, GREEN("绿灯") { public TrafficLight next() { return RED; } }, YELLOW("黄灯") { public TrafficLight next() { return GREEN; } }, ; private final String desc; TrafficLight (String desc) { this.desc = desc; } public String getDesc() { return desc; } public abstract TrafficLight next(); } 根据上面的描述:第一个问题:Direction d = Direction.EAST;的答案就很显然了,赋值枚举变量的时候,当然要带前缀了,因为这些枚举常量是指定枚举类中的常量,必须加上类限定前缀。java的switch语法,是通过jvm的tableswitch和lookupswitch两个指令实现。简单说一下实现原理:java编译器为switch语句编译成一个局部变量数组,每个case对应一个数组的索引,指令的执行是通过不同的数组索引找到不同的入口指令。所以原则上switch...case只能处理int型的变量。 enum能用在switch语句中,也是一个语法糖,我们知道所有枚举类的父类Enum中有一个private final int ordinal;,java编译器检测到switch语句中变量是一个枚举类,则会利用之前枚举类的ordinal属性,编译一个局部变量数组,后续在进行case分支比较的时候,就是简单通过tableswitch或lookupswitch指令来进行跳转,需要注意的一点:这个局部变量数组的构建过程是在编译器在编译阶段完成的。给一个简单的实例: public class Traffic { public static void main(String[] args) { Light light = Light.RED; switch(light) { case RED: System.out.println("红灯"); break; case GREEN: System.out.println("绿灯"); break; case YELLOW: System.out.println("黄灯"); break; } } enum Light { RED, GREEN, YELLOW } } javap -c 反编译后的字节码: public class com.lee.test.Traffic extends java.lang.Object{ public com.lee.test.Traffic(); Code: 0: aload_0 1: invokespecial #10; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #18; //Field com/lee/test/Traffic$Light.RED:Lcom/lee/test/Traffic$Light; 3: astore_1 4: invokestatic #24; //Method $SWITCH_TABLE$com$lee$test$Traffic$Light:()[I 7: aload_1 8: invokevirtual #27; //Method com/lee/test/Traffic$Light.ordinal:()I 11: iaload 12: tableswitch{ //1 to 3 1: 40; 2: 51; 3: 62; default: 70 } 40: getstatic #31; //Field java/lang/System.out:Ljava/io/PrintStream; 43: ldc #37; //String 红灯 45: invokevirtual #39; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 48: goto 70 51: getstatic #31; //Field java/lang/System.out:Ljava/io/PrintStream; 54: ldc #45; //String 绿灯 56: invokevirtual #39; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 59: goto 70 62: getstatic #31; //Field java/lang/System.out:Ljava/io/PrintStream; 65: ldc #47; //String 黄灯 67: invokevirtual #39; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 70: return static int[] $SWITCH_TABLE$com$lee$test$Traffic$Light(); Code: 0: getstatic #53; //Field $SWITCH_TABLE$com$lee$test$Traffic$Light:[I 3: dup 4: ifnull 8 7: areturn 8: pop 9: invokestatic #55; //Method com/lee/test/Traffic$Light.values:()[Lcom/lee/test/Traffic$Light; 12: arraylength 13: newarray int 15: astore_0 16: aload_0 17: getstatic #59; //Field com/lee/test/Traffic$Light.GREEN:Lcom/lee/test/Traffic$Light; 20: invokevirtual #27; //Method com/lee/test/Traffic$Light.ordinal:()I 23: iconst_2 24: iastore 25: goto 29 28: pop 29: aload_0 30: getstatic #18; //Field com/lee/test/Traffic$Light.RED:Lcom/lee/test/Traffic$Light; 33: invokevirtual #27; //Method com/lee/test/Traffic$Light.ordinal:()I 36: iconst_1 37: iastore 38: goto 42 41: pop 42: aload_0 43: getstatic #62; //Field com/lee/test/Traffic$Light.YELLOW:Lcom/lee/test/Traffic$Light; 46: invokevirtual #27; //Method com/lee/test/Traffic$Light.ordinal:()I 49: iconst_3 50: iastore 51: goto 55 54: pop 55: aload_0 56: dup 57: putstatic #53; //Field $SWITCH_TABLE$com$lee$test$Traffic$Light:[I 60: areturn Exception table: from to target type 16 25 28 Class java/lang/NoSuchFieldError 29 38 41 Class java/lang/NoSuchFieldError 42 51 54 Class java/lang/NoSuchFieldError } } 根据上述的描述: 枚举变量的定义、赋值是运行时jvm强制要求类型必须一致,所以必须加上类限定前缀;而在switch...case中使用枚举变量,则只是java提供的语法糖,这个特色并不是在运行时通过JVM来保证的,而只是java编译器在编译阶段完成的,在编译过程中的一旦判断switch语句中的变量是enum类型,即只需要以其ordinal属性为索引,通过tableswitch查找局部变量数组(这在反编译后的7~12行字节码可以体现出)。在此时case语句不需要类限定前缀,完全是java编译器的限制(编译器是不需要枚举类的前缀,只需要枚举类编译的static int[] $SWITCH_TABLE)。 JDK7中switch...case语法新增支持string字面量是差不多同样的道理,java编译器根据string常量的hashcode值,在编译阶段构建局部常量数组。

蛮大人123 2019-12-02 01:57:42 0 浏览量 回答数 0

问题

dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?【Java问答学堂】49期

剑曼红尘 2020-07-02 17:35:03 17 浏览量 回答数 1

回答

Java Java核心技术·卷 I(原书第10版)| Core Java Volume 讲的很全面,书中的代码示例都很好,很适合Java入门。 但是作者不太厚道的是把现在没人用的GUI编程放在了第一卷,基本上10~13章是可以不用读的。 Java性能权威指南|Java Performance: The Definitive Guide 市面上介绍Java的书有很多,但专注于Java性能的并不多,能游刃有余地展示Java性能优化难点的更是凤毛麟角,本书即是其中之一。 通过使用JVM和Java平台,以及Java语言和应用程序接口,本书详尽讲解了Java性能调优的相关知识,帮助读者深入理解Java平台性能的各个方面,最终使程序如虎添翼。 实战Java高并发程序设计|葛一鸣 由部分段落的行文来看,搬了官方文档。 也有一些第一人称的叙述和思考,也能看出作者也是花了一点心思的。胜在比较基础,涉及到的知识点也还很全面(讲到了流水线计算和并发模型这些边边角角的),但是由于是编著,全书整体上不够统一和深入,适合作为学习高并发的第一本工具书。 Java 8实战 对Java8的新特性讲解的十分到位,尤其是lamdba表达式和流的操作。 再者对于Java8并发处理很有独到见解。对于并行数据处理和组合式异步编程还需要更深的思考才能更加掌握。 推荐给再用java8但没有去真正了解的人看,有很多你不知道的细节、原理和类库设计者的用心良苦在里面、内容没有很难,抽出几个小时就能看完,花费的时间和收获相比,性价比很高。 Java并发编程实战 先不谈本书的内容如何,光书名就足够吸引不少目光。“并发”这个词在Java世界里往往和“高级、核心”等字眼相联系起来,就冲着这两个字,都将勾起软件工程师们埋藏在心底那种对技术的探索欲和对高级API的驾驭感。 程序员嘛,多少都有点职业病。其实Java对“并发”优化从未停止过,从5.0到7.0,几乎每个版本的新特性里,都会针对前一版本在“并发”上有所改进。这种改进包括提供更丰富的API接口、JVM底层性能优化等诸多方面。 Thinking in Java 很美味的一本书,不仅有icecreamm,sundae,sandwich,还有burrito!真是越看越饿啊~ Effective Java中文版(第3版)|Effective Java Third Edition Java 高阶书籍,小白劝退。介绍了关于Java 编程的90个经验技巧。 作者功力非常强悍,导致这本书有时知识面迁移很广。总之,非常适合有一定Java开发经验的人阅读提升。 深入理解Java虚拟机(第3版)| 周志明 浅显易懂。最重要的是开启一扇理解虚拟机的大门。 内存管理机制与Java内存模型、高效并发这三章是特别实用的。 Java虚拟机规范(Java SE 8版)|爱飞翔、周志明 整本书就觉得第二章的方法字节码执行流程,第四章的前8节和第五章能看懂一些。其他的过于细致和琐碎了。 把Java字节码讲的很清楚了,本质上Java虚拟机就是通过字节码来构建的一套体系罢了。所以字节码说的非常细致深入。 数据&大数据 数据结构与算法分析|Data Structures and Algorithm Analysis in Java 数据结构是计算机的核心,这部书以java语言为基础,详细的介绍了基本数据结构、图、以及相关的排序、最短路径、最小生成树等问题。 但是有一些高级的数据结构并没有介绍,可以通过《数据结构与算法分析——C语言描述》来增加对这方面的了解。 MySQL必知必会 《MySQL必知必会》MySQL是世界上最受欢迎的数据库管理系统之一。 书中从介绍简单的数据检索开始,逐步深入一些复杂的内容,包括联结的使用、子查询、正则表达式和基于全文本的搜索、存储过程、游标、触发器、表约束,等等。通过重点突出的章节,条理清晰、系统而扼要地讲述了读者应该掌握的知识,使他们不经意间立刻功力大增。 数据库系统概念|Datebase System Concepts(Fifth Edition) 从大学读到现在,每次拿起都有新的收获。而且这本书还是对各个数据相关领域的概览,不仅仅是数据库本身。 高性能MySQL 对于想要了解MySQL性能提升的人来说,这是一本不可多得的书。 书中没有各种提升性能的秘籍,而是深入问题的核心,详细的解释了每种提升性能的原理,从而可以使你四两拨千斤。授之于鱼不如授之于渔,这本书做到了。 高可用MySQL 很实用的书籍,只可惜公司现有的业务和数据量还没有达到需要实践书中知识的地步。 利用Python进行数据分析|唐学韬 内容还是跟不上库的发展速度,建议结合里面讲的库的文档来看。 内容安排上我觉得还不错,作者是pandas的作者,所以对pandas的讲解和设计思路都讲得很清楚。除此以外,作者也是干过金融数据分析的,所以后面专门讲了时间序列和金融数据的分析。 HBase 看完影印版第一遍,开始以为会是大量讲API,实际上除了没有将HBase源代码,该讲的都讲了,CH8,9章留到最后看的,确实有点顿悟的感觉,接下来需要系统的看一遍Client API,然后深入代码,Come ON! Programming Hive Hive工具书,Hive高级特性。 Hadoop in Practice| Alex Holmes 感觉比action那本要强 像是cookbook类型的 整个过完以后hadoop生态圈的各种都接触到了 这本书适合当参考手册用。 Hadoop技术内幕|董西成 其实国人能写这样的书,感觉还是不错的,不过感觉很多东西不太深入,感觉在深入之前,和先有整体,带着整体做深入会更好一点, jobclient,jobtracer,tasktracer之间的关系最好能系统化 Learning Spark 很不错,core的原理部分和api用途解释得很清楚,以前看文档和代码理解不了的地方豁然开朗。 不足的地方是后几章比较弱,mllib方面没有深入讲实现原理。graphx也没有涉及 ODPS权威指南 基本上还算一本不错的入门,虽然细节方面谈的不多,底层也不够深入,但毕竟是少有的ODPS书籍,且覆盖面很全,例子也还行。 数据之巅|徐子沛 从一个新的视角(数据)切入,写美国历史,统计学的发展贯穿其中,草蛇灰线,伏脉千里,读起来波澜壮阔。 消息队列&Redis RabbitMQ实战 很多年前的书了,书中的例子现在已经不适用了,推荐官方教程。 一些基础还是适用,网上也没有太多讲rab的书籍,将就看下也行,我没用过所以…. Apache Kafka源码剖析|徐郡明 虽然还没看,但知道应该不差。我是看了作者的mybatis源码分析,再来看这本的,相信作者。 作者怎么有这么多时间,把框架研究的这么透彻,佩服,佩服。 深入理解Kafka:核心设计与实践原理|朱忠华 通俗易懂,图文并茂,用了很多图和示例讲解kafka的架构,从宏观入手,再讲到细节,比较好,值得推荐。 深入理解Kafka是市面上讲解Kafka核心原理最透彻的,全书都是挑了kafka最核心的细节在讲比如分区副本选举、分区从分配、kafka数据存储结构、时间轮、我认为是目前kafka相关书籍里最好的一本。 Kafka 认真刷了 kafka internal 那章,看了个talk,算是入了个门。 系统设计真是门艺术。 RocketMQ实战与原理解析|杨开元 对RocketMQ的脉络做了一个大概的说明吧,深入细节的东西还是需要自己看代码 Redis设计与实现|黄健宏 部分内容写得比较啰嗦,当然往好了说是对新手友好,不厌其烦地分析细节,但也让整本书变厚了,个人以为精炼语言可以减少20%的内容。 对于有心一窥redis实现原理的读者来说,本书展露了足够丰富的内容和细节,却不至于让冗长的实现代码吓跑读者——伪代码的意义在此。下一步是真正读源码了。 Redis 深度历险:核心原理与应用实践|钱文品 真心不错,数据结构原理+实际应用+单线程模型+集群(sentinel, codis, redis cluster), 分布式锁等等讲的都十分透彻。 一本书的作用不就是系统性梳理,为读者打开一扇窗,读者想了解更多,可以自己通过这扇窗去Google。这本书的一个瑕疵是最后一章吧,写的仓促了。不过瑕不掩瑜。 技术综合 TCP/IP详解 卷1:协议 读专业性书籍是一件很枯燥的事,我的建议就是把它作为一本手册,先浏览一遍,遇到问题再去详细查,高效。 Netty in Action 涉及到很多专业名词新概念看英文原版顺畅得多,第十五章 Choosing the right thread model 真是写得太好了。另外结合Ron Hitchens 写的《JAVA NIO》一起看对理解JAVA NIO和Netty还是很有帮助的 ZooKeeper 值得使用zookeeper的人员阅读, 对于zookeeper的内部机制及api进行了很详细的讲解, 后半部分深入地讲解了zookeeper中ensemble互相协作的流程, 及group等高级配置, 对zookeeper的高级应用及其它类似系统的设计都很有借鉴意义. 从Paxos到Zookeeper|倪超 分布式入门鼻祖,开始部分深入阐述cap和base理论,所有的分布式框架都是围绕这个理论的做平衡和取舍,中间 zk的原理、特性、实战也讲的非常清晰,同时讲cap理论在zk中是如何体现,更加深你对cap的理解. 深入理解Nginx(第2版)|陶辉 云里雾里的快速读了一遍,主要是读不懂,读完后的感受是设计的真好。 原本是抱着了解原理进而优化性能的想法来读的,却发现书中的内容都是讲源码,作者对源码的注释超级详细,非常适合开发者,但不适合使用者,给个五星好评是因为不想因为我这种菜鸡而埋没了高质量内容。 另外别人的代码写的真好看,即便是过程式语言程序也吊打我写的面向对象语言程序。 作者是zookeeper的活跃贡献者,而且是很资深的研究员,内容比较严谨而且较好的把握住了zk的精髓。书很薄,但是没有废话,选题是经过深思熟虑的。 深入剖析Tomcat 本书深入剖析Tomcat 4和Tomcat 5中的每个组件,并揭示其内部工作原理。通过学习本书,你将可以自行开发Tomcat组件,或者扩展已有的组件。 Tomcat是目前比较流行的Web服务器之一。作为一个开源和小型的轻量级应用服务器,Tomcat 易于使用,便于部署,但Tomcat本身是一个非常复杂的系统,包含了很多功能模块。这些功能模块构成了Tomcat的核心结构。本书从最基本的HTTP请求开始,直至使用JMX技术管理Tomcat中的应用程序,逐一剖析Tomcat的基本功能模块,并配以示例代码,使读者可以逐步实现自己的Web服务器。 深入理解计算机系统 | 布莱恩特 无论是内容还是纸张印刷,都是满分。计算机学科的集大成之作。引导你如何练内功的,算是高配版本的计算机导论,目的是釜底抽薪引出来操作系统、组成原理这些专业核心的课程。帮助我们按图索骥,点亮一个一个技能树。 架构探险分布式服务框架 | 李业兵 刚看前几章的时候,心里满脑子想得都是这特么贴一整页pom文件代码上来干鸡毛,又是骗稿费的,买亏了买亏了,后来到序列化那章开始,诶?还有那么点意思啊。 到服务注册中心和服务通讯,60块钱的书钱已经赚回来了。 知识是无价的,如果能花几十块钱帮你扫了几个盲区,那就是赚了。 深入分析JavaWeb技术内幕 | 许令波 与这本书相识大概是四年前是在老家的北方图书城里,当时看到目录的感觉是真的惊艳,对当时刚入行的自己来说,这简直就是为我量身定做的扫盲科普集啊。 但是可惜的是,这本书在后来却一直没机会读上。然后经过四年的打怪升级之后,这次的阅读体验依旧很好。 其中,java编译原理、 Servlet工作原理、 Tomcat、spring和iBatis这几章的收获很大。 前端 jQuery 技术内幕| 高云 非常棒的一本书,大大降低了阅读jquery源码的难度(虽然还是非常难)。 Head First HTML与CSS(第2版) 翻了非常久的时间 断断续续 其实从头翻到尾 才发现一点都不难。 可我被自己的懒惰和畏难情绪给拖累了 简单说 我成了自己往前探索的负担。网页基础的语法基本都涵盖了 限于文本形态 知识点都没法像做题一样被反复地运用和复习到。通俗易懂 这不知算是多高的评价? 作为入门真心算不错了 如果更有耐心 在翻完 HTML 后 对 CSS 部分最好是可以迅速过一遍 找案例练习估计更好 纸上得来终觉浅 总是这样。 JavaScript高级程序设计(第3版) JavaScript最基础的书籍,要看认真,慢慢地看,累计接近1000小时吧。而且对象与继承,性能优化,HTML5 api由于没有实践或缺乏代码阅读量导致看的很糊涂,不过以后可以遇到时再翻翻,或者看更专业的书。 深入理解ES6 Zakas的又一部杰作,他的作品最优秀的地方在于只是阐述,很少评价,这在帮助我们夯实基础时十分有意义,我也喜欢这种风格。 我是中英文参照阅读的,译本后半部分有一些文字上的纰漏,但是总体来说忠实原文,水平还是相当不错,希望再版时可以修复这些文字问题。 高性能JavaScript 还是挺不错的。尤其是对初学者。总结了好多程序方面的好习惯。 不过对于老手来说,这些常识已经深入骨髓了。 深入浅出Node.js|朴灵 本书是我看到现在对Node.JS技术原理和应用实践阐述的最深入,也最全面的一本书。鉴于作者也是淘宝的一位工程师,在技术总是国外好的大环境下,没有理由不给本书五颗星。 作者秉着授人于鱼不如授人于渔的精神,细致入微的从V8虚拟机,内存管理,字符串与Buffer的应用,异步编程的思路和原理这些基础的角度来解释Node.JS是如何工作的,比起市面上众多教你如何安装node,用几个包编写一些示例来比,本书绝对让人受益匪浅。 认真看完本书,几乎可以让你从一个Node的外行进阶到专家的水平。赞! 总结 其实我觉得在我们现在这个浮躁的社会,大家闲暇时间都是刷抖音,逛淘宝,微博……他们都在一点点吞噬你的碎片时间,如果你尝试着去用碎片的时间看看书,我想时间久了你自然能体会这样的好处。 美团技术团队甚至会奖励读完一些书本的人,很多公司都有自己的小图书馆,我觉得挺好的。 文章来自:敖丙

剑曼红尘 2020-03-20 14:52:22 0 浏览量 回答数 0

问题

【漏洞公告】CVE-2017-5645:Apache Log4j反序列化漏洞

正禾 2019-12-01 21:50:46 3822 浏览量 回答数 0

回答

1.阻塞与同步2.BIO与NIO对比3.NIO简介4.缓冲区Buffer5.通道Channel6.反应堆7.选择器8.NIO源码分析9.AIO1.阻塞与同步1)阻塞(Block)和非租塞(NonBlock):阻塞和非阻塞是进程在访问数据的时候,数据是否准备就绪的一种处理方式,当数据没有准备的时候阻塞:往往需要等待缞冲区中的数据准备好过后才处理其他的事情,否則一直等待在那里。非阻塞:当我们的进程访问我们的数据缓冲区的时候,如果数据没有准备好则直接返回,不会等待。如果数据已经准备好,也直接返回2)同步(Synchronization)和异步(Async)的方式:同步和异步都是基于应用程序私操作系统处理IO事件所采用的方式,比如同步:是应用程序要直接参与IO读写的操作。异步:所有的IO读写交给搡作系统去处理,应用程序只需要等待通知。同步方式在处理IO事件的时候,必须阻塞在某个方法上靣等待我们的IO事件完成(阻塞IO事件或者通过轮询IO事件的方式).对于异步来说,所有的IO读写都交给了搡作系统。这个时候,我们可以去做其他的事情,并不拓要去完成真正的IO搡作,当搡作完成IO后.会给我们的应用程序一个通知同步:阻塞到IO事件,阻塞到read成则write。这个时候我们就完全不能做自己的事情,让读写方法加入到线程里面,然后阻塞线程来实现,对线程的性能开销比较大,参考:https://blog.csdn.net/CharJay_Lin/article/details/812598802.BIO与NIO对比block IO与Non-block IO1)区别IO模型 IO NIO方式 从硬盘到内存 从内存到硬盘通信 面向流(乡村公路) 面向缓存(高速公路,多路复用技术)处理 阻塞IO(多线程) 非阻塞IO(反应堆Reactor)触发 无 选择器(轮询机制)2)面向流与面向缓冲Java NIO和IO之间第一个最大的区别是,IO是面向流的.NIO是面向缓冲区的。Java IO面向流意味着毎次从流中读一个成多个字节,直至读取所有字节,它们没有被缓存在任何地方,此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的教据,需要先将它缓存到一个缓冲区。Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,霱要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数裾。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。3)阻塞与非阻塞Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。4)选择器(Selector)Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择"通道:这些通里已经有可以处理的褕入,或者选择已准备写入的通道。这选怿机制,使得一个单独的线程很容易来管理多个通道。5)NIO和BIO读取文件BIO读取文件:链接BIO从一个阻塞的流中一行一行的读取数据image | left | 469x426NIO读取文件:链接通道是数据的载体,buffer是存储数据的地方,线程每次从buffer检查数据通知给通道image | left | 559x3946)处理数据的线程数NIO:一个线程管理多个连接BIO:一个线程管理一个连接3.NIO简介在Java1.4之前的I/O系统中,提供的都是面向流的I/O系统,系统一次一个字节地处理数据,一个输入流产生一个字节的数据,一个输出流消费一个字节的数据,面向流的I/O速度非常慢,而在Java 1.4中推出了NIO,这是一个面向块的I/O系统,系统以块的方式处理处理,每一个操作在一步中产生或者消费一个数据库,按块处理要比按字节处理数据快的多。在NIO中有几个核心对象需要掌握:缓冲区(Buffer)、通道(Channel)、选择器(Selector)。参考:链接image2.png | center | 851x3834.缓冲区Buffer缓冲区实际上是一个容器对象,更直接的说,其实就是一个数组,在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,它也是写入到缓冲区中的;任何时候访问 NIO 中的数据,都是将它放到缓冲区中。而在面向流I/O系统中,所有数据都是直接写入或者直接将数据读取到Stream对象中。在NIO中,所有的缓冲区类型都继承于抽象类Buffer,最常用的就是ByteBuffer,对于Java中的基本类型,基本都有一个具体Buffer类型与之相对应,它们之间的继承关系如下图所示:image3.png | center | 650x3681)其中的四个属性的含义分别如下:容量(Capacity):缓冲区能够容纳的数据元素的最大数量。这一个容量在缓冲区创建时被设定,并且永远不能改变。上界(Limit):缓冲区的第一个不能被读或写的元素。或者说,缓冲区中现存元素的计数。位置(Position):下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新。标记(Mark):下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新。2)Buffer的常见方法如下所示:flip(): 写模式转换成读模式rewind():将 position 重置为 0 ,一般用于重复读。clear() :compact(): 将未读取的数据拷贝到 buffer 的头部位。mark(): reset():mark 可以标记一个位置, reset 可以重置到该位置。Buffer 常见类型: ByteBuffer 、 MappedByteBuffer 、 CharBuffer 、 DoubleBuffer 、 FloatBuffer 、 IntBuffer 、 LongBuffer 、 ShortBuffer 。3)基本操作Buffer基础操作: 链接缓冲区分片,缓冲区分配,直接缓存区,缓存区映射,缓存区只读:链接4)缓冲区存取数据流程存数据时position会++,当停止数据读取的时候调用flip(),此时limit=position,position=0读取数据时position++,一直读取到limitclear() 清空 buffer ,准备再次被写入 (position 变成 0 , limit 变成 capacity) 。5.通道Channel通道是一个对象,通过它可以读取和写入数据,当然了所有数据都通过Buffer对象来处理。我们永远不会将字节直接写入通道中,相反是将数据写入包含一个或者多个字节的缓冲区。同样不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。image4.png | center | 368x191在NIO中,提供了多种通道对象,而所有的通道对象都实现了Channel接口。它们之间的继承关系如下图所示:image5.png | center | 650x5171)使用NIO读取数据在前面我们说过,任何时候读取数据,都不是直接从通道读取,而是从通道读取到缓冲区。所以使用NIO读取数据可以分为下面三个步骤:从FileInputStream获取Channel 创建Buffer 将数据从Channel读取到Buffer中 例子:链接 2)使用NIO写入数据使用NIO写入数据与读取数据的过程类似,同样数据不是直接写入通道,而是写入缓冲区,可以分为下面三个步骤:从FileInputStream获取Channel 创建Buffer 将数据从Channel写入到Buffer中 例子:链接 6.反应堆1)阻塞IO模型在老的IO包中,serverSocket和socket都是阻塞式的,因此一旦有大规模的并发行为,而每一个访问都会开启一个新线程。这时会有大规模的线程上下文切换操作(因为都在等待,所以资源全都被已有的线程吃掉了),这时无论是等待的线程还是正在处理的线程,响应率都会下降,并且会影响新的线程。image6.png | center | 739x3362)NIOJava NIO是在jdk1.4开始使用的,它既可以说成“新IO”,也可以说成非阻塞式I/O。下面是java NIO的工作原理:1.由一个专门的线程来处理所有的IO事件,并负责分发。2.事件驱动机制:事件到的时候触发,而不是同步的去监视事件。3.线程通讯:线程之间通过wait,notify等方式通讯。保证每次上下文切换都是有意义的。减少无谓的线程切换。image7.png | center | 689x251注:每个线程的处理流程大概都是读取数据,解码,计算处理,编码,发送响应。7.选择器传统的 server / client 模式会基于 TPR ( Thread per Request ) .服务器会为每个客户端请求建立一个线程.由该线程单独负贵处理一个客户请求。这种模式带未的一个问题就是线程数是的剧增.大量的线程会增大服务器的开销,大多数的实现为了避免这个问题,都采用了线程池模型,并设置线程池线程的最大数量,这又带来了新的问题,如果线程池中有 200 个线程,而有 200 个用户都在进行大文件下载,会导致第 201 个用户的请求无法及时处理,即便第 201 个用户只想请求一个几 KB 大小的页面。传统的 Sorvor / Client 模式如下围所示:image8.png | center | 597x286NIO 中非阻塞IO采用了基于Reactor模式的工作方式,IO调用不会被阻塞,相反是注册感兴趣的特点IO事件,如可读数据到达,新的套接字等等,在发生持定率件时,系统再通知我们。 NlO中实现非阻塞IO的核心设计Selector,Selector就是注册各种IO事件的地方,而且当那些事件发生时,就是这个对象告诉我们所发生的事件。image9.png | center | 462x408当有读或者写等任何注册的事件发生时,可以从Selector中获得相应的SelectionKey,同时从SelectionKey中可以找到发生的事件和该事件所发生的具体的SelectableChannel,以获得客户端发送过来的数据。使用NIO中非阻塞IO编写服务器处理程序,有三个步骤1.向Selector对象注册感兴趣的事件2.从Selector中获取感兴趣的事件3.根据不同事件进行相应的处理8.NIO源码分析Selector是NIO的核心epool模型1)SelectorSelector的open()方法:链接2)ServerSocketChannelServerSocketChannel.open() 链接9.AIOAsynchronous IO异步非阻塞IOBIO ServerSocketNIO ServerSocketChannelAIO AsynchronousServerSocketChannel

wangccsy 2019-12-02 01:46:51 0 浏览量 回答数 0

问题

【精品问答】Java必备核心知识1000+(附源码)

问问小秘 2019-12-01 22:00:28 870 浏览量 回答数 1

问题

Java 中的Redis Monitor命令

落地花开啦 2019-12-01 19:47:02 1566 浏览量 回答数 1
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站