热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

今日份阿里Java后端面试真题,看完你学会了嘛?附面试福利

本文转载自:今日份阿里Java后端面试真题,看完你学会了嘛?附面试福利一.谈谈你对Java平台的理解?“Java是解释执行”,这句话正确么?典型回答:Java本身是一种面向对象的语

本文转载自:今日份阿里Java后端面试真题,看完你学会了嘛?附面试福利


一. 谈谈你对Java平台的理解? “Java 是解释执行”,这句话正确么?

典型回答:

Java本身是一种面向对象的语言,最显著的特点有两个方面,一个是所谓的"书写一次,到处运行";能够非常容易地获得跨平台能力;另外就是垃圾收集器(GC),Java通 过垃圾收集器回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收。我们日常接触到JRE或者JDK。JRE也就是Java运行环境,包含了JVM和Java类库,以及一些模块等。而JDK可以看作是JRE的一个超集,提供了更多的工具,比如编译器各种诊断工具。

"对于Java是解释执行"这句话,这个说法不准确。我们开发的Java的源代码,首先通过Javac编译成为字节码,然后在运行时通过Java虚拟机内嵌的解释器将字节码转换为最终的机器码。但是常见的JVM,比如我们大数据情况使用的0racleJDK提供的HostpotJVM,提供了JIT编译器,就是通常所说的动态编译器,JIT能够在运行时将热点代码(高频调用的方法和代码块)编译成机器码,这种情况下部分热点就属于编译执行,而不是解释执行。这样类似于缓存技术,运行时在遇到热点代码可以直接执行,而不是先解释在执行。

知识扩展:

在运行时 , JVM通过类加载器加载字节码,解释或者编译执行。就像我们前面提到的,主流的Java版本中,如JDK8实际是解释和编译混合的一种模式,即所谓的混合模式。JIT编译器分为多种模式(Server模式C1ient模式AOT模式)通常运行在Server模式的JVM,会进行上万次调用以收集足够的信息进行高效编译,client模式这个门限是1500次。

Oracle Hostpot JVM内置了两个不同的JIT compiler,C1对应 前面说的client模式,适用于对于启动速度敏感的应用,比如普通Java桌面应用;C2对应Server模式,它的优点是为长时间运行的服务器端应用设计的。

Java虚拟机启动时, 可以指定不同的参数对运行模式进行选择。比如,执行"-Xint",就是告诉JVM只进行解释执行,不对代码进行编译,这种模式抛弃了JIT可能带来的性能优势。毕竟解释器是逐条读入,逐条解释运行的。与其相对性的,还有一个"Xcomp"参数,这是告诉JVM关闭解释器,不要进行解释执行,或者叫做最大优化级别。那你可能会问这种模式是不是最高效啊?简单来说,还真未必。"-Xcomp" 会导致JVM启动变慢非常多…

除了日常最常见的Java使用模式,其实还有一种新的编译方式,即所谓的AOT,直接将字节码编译成机器码,这样就避免了JIT预热等各方面的开销,比如Oracle JDK 9就引入了实性质的AOT特性,并且增加了jaotc工具。

另外,JVM作为一个强大的平台,不仅仅只有Java语言可以运行在JVM上,本质上合规的字节码都可以运行,Java语言自身也为此提供了便利,我们可以看到类似ClojureScala Groovy JRuby Jython等 大量JVM语言,活跃在不同的场景。

二. 请对比Exception和Error,另外,运行时异常与一般异常有什么区别?

典型回答:

Exception和Error都是继承了Throwable类,在Java中只有Throwable类型的实例才可以被抛出或者捕获,它是异常处理机制的基本组成类型。Exceptoin和Error体现了Java平台设计者对于不同异常情况的分类。Exception是程序正常运行中,可以预料的意外情况,可以并且应该被捕获,进行相应处理。Error是指在正常情况下,不大可能出现的情况,绝大部分的Error都会导致处于非正常的不可恢复状态。既然是非正常情况,所以不便于也不需要捕获,常见的比如.OutofMemoryError之类,都是Error的子类。

Exceptoin又分为可检查异常和不检查异常,可检查异常在代码里必须显示地进行捕获处理,这是编译器检查的一部分。不检查异常就是所谓的运行时异常,类似于Nul1PointerException ArrayIndex0utofBoundsException之类,通常是可以编码避免的逻辑错误,具体根据需要来进行判断是否需要捕获,并不会在编译期强制要求。

知识扩展:

在开发中尽量不要捕获类似Exceptio这样的通用异常,而是应该捕获特定异常.这是因为我们在日常的开发和合作中,我们读代码的机会往往超过写代码,软,件工程是门协作的艺术,所以我们有义务让自己的代码能够直接地体现出尽量多的信息,而泛泛的Exception之类,恰恰隐藏了我们的目的。另外,我们也要保证程序不会捕获到我们不希望捕获的异常。比如,你可能更希望RuntimeException 被扩散出来,而不是被捕获。

在开发中不要生吞异常。这是异常处理中要特别注意的事情,因为很可能会导致非常难以诊断的诡异情况。生吞异常,往往是基于假设这段代码可能不会发生,或者感觉忽略异常是无所谓的,但是千万不要在产品代码做这种假设!如果我们不把异常抛出来,或者也没有输出日志之类,程序可能在后续代码以不可控的方式结束。没有人能够轻易判断究竟是哪里出了异常,以及是什么原因产生了异常。

在开发中不要输出标准错误(STERR),因为有时候你很难判断出到底输出到哪里去了。尤其是分布式系统,如果发生异常,但是无法找到堆栈轨迹,这纯属是为诊断设置障碍。所以最好使用产品日志,详细地输出到日志系统里。

Throw early,catch late。在开发中可能会出现各种情况,比如获取配置失败之类的。在发现问题的时候,第一时间抛出,能够更加清晰地反映问题,这是Throw early。 catch late就是 我们经常烦恼的问题,捕获异常后,需要怎么处理?最差的方式,就是我们前面提到的"生吞异常",本质上就是掩盖问题。如果实在不知道如何处理,可以选择保留原有异常的cause信息,直接再抛出或者构建新的异常抛出去。在更高层,因为有了清晰的(业务)逻辑,往往会更清楚合适的处理方式是什么。

有时候,我们会根据需要自己定义异常,这个时候除了保证提供足够的信息,还需要考虑两点。一是否需要定异常CheckedException,因为这种类型的设计初衷是为了从异常情况恢复,作为异常设计者,我们往往有充足信息进行分类。在保证诊断信息足够的同时,也要考虑避免包含敏感信息,因为那样可能会导致潜在的安全问题。如果我们看Java的标准类库,你可能注意到类似java. net. ConnectException,出错信息是类似"Connection refused", 而不包含具体的机器名IP端口等,一个重要的考量就是信息安全。类似的情况在日志系统中也有,比如,用户数据一般是不可以输出到日志里面的。

try-catch代码段会产生额外的性能开销,或者换个角度来说,它往往会影响JVM对代码进行优化,所以建议仅捕获有必要的代码段.尽量不要一个大的try包住整段代码,与此同时,利用异常控制代码流程,也不是一个好主意,远比我们通常意义上的条件语句要低效。

额外:

NoClassDeF oundError和ClassNotFoundException的区别?

首先NoClassDeFoundError是一个错误,ClassNotFoundException是一个异常。ClassNotFoundException的产生原因,Java支持使用Class. froName方法来动态地加载类,任意一个类的类名如果被作为参数传递给这个方法都将导致该类被加载到JVM内存中,如果这个类在类路径中没有被找到,那么此时就会在运行时拋出ClassNotFoundException异常。

另外还有一个导致ClassNotFoundException的原因就是,当一个类已经被某个类加载器加载到内存中,此时另一个类加载器又尝试着动态地从同一个包中加载这个类。

NoClassDeFoundError产生的原因在于:如果JVM或者ClassLoader实例尝试加载类的时候找不到类的定义。例如要查找的类在编译的时候是存在的,运行的时候,找不到了。这个时候就会导致NoClassDefFoundError.造成该问题的原因可能是打包过程中漏掉了部分类,或者jar包出现损坏或者篡改。解决这个问题的办法就是查找那些在开发期间存在与类路径下,但在运行期间却不在类路径下的类。

三. 对比Hashtable、HashMap、TreeMap有什么不同?

典型回答:

HashTable HashMap TreeMap都是最常见的一些Map实 现,是以键值对的形式存储和操作数据的容器类型。

HashTable是早期Java类库提供的一个哈希表实现,本身是同步的,不支持nu11键和值,由于同步导致的性能开销,所以已经很少被推荐使用。

HashMap是应用更加广泛的哈希表实现,行为大致.上与HashTable- -致,主要区别在于HashMap不是同步的,支持nul1键和值等。通常情况下, HashMap进行put或者get操作,可以达到常数时间的性能,所以它是绝大部分利用键值对存储场景的首选,比如,实现一个用户ID和用户信息对应的运行时存储结构。

TreeMap则是基于红黑树的一种提供顺序访问的Map,和HashMap不同,它的getremove之类操作都是0(long(n)的时间复杂度,具体顺序可以由指定的Comparator来决定或者根据键的自然顺序来判断。

知识扩展:

HashMap实现原理是经常被问到的一个问题,以下基于JDK1.8分析。

1. 内部存储

HashMap的内部存储是一个数组,数组的元素Node实现了Map.Entry接口(hash, key, value, next) , next非空时指向定位相同的另一个Entry,如图:

今日份阿里Java后端面试真题,看完你学会了嘛?附面试福利

JDK 8之前,其内部是由数组+链表来实现的,而JDK 8对于链表长度超过8的链表将转储为红黑树。

2. 容量(capacity)和负载因子(loadFactor)

简单的说, capacity就是数组的大小,loadFactory就是数组填满程度的最大比列。当数组中的元素的数目大于capaci ty*loadFactor时就需要扩容,调整数组的大小为当前的2 倍。同时初始化容量的大小也是2的次幂(大于等于设定容量的最小次幂),则数组的大小在扩容前后都将是2的次幂。默认的容量为16,负载因子为0.75。

3. put方法的大致的思路

  • 如果key的值为null,则将该键值对添加到table[0]处,遍历该链表,如果有key为null,则将value替换。
  • 如果key不为null,获取key的hashCode值,经过indexFor()方法运算得到的值作为标识,但由于hashCode的值并不唯一,经过运算获取的值也不能保证唯一(哈希冲突),所以,经过以上运算得来的数值只能作为数组的索引。
  • 当通过索引定位到这个节点时,在遍历该链表,判断是否存在相同的key对象,如果存在就用新的value覆盖旧的value
  • 如果不存在,就创建一个Entry对象添加到table[i]处,如果table[i]已经存在其他元素,那么新Entry对象将会保存在链表的表头,通过next指针指向原有的Entry对象,形成链表结构。
  • 当链表的结构太长时(默认超过8个元素),链表就会转为红黑树。

4. get方法的大致的思路

  • 对key进行nu11检查。如果key是nu11,table[0]这个位置的元素将被返回
  • key的hashcode() 方法被调用,然后计算hash值。
  • indexFor (hash, table. length)用来计算要获取的Entry对象在table数组中的精确的位置(使用刚才计算的hash值)
  • 在获取了table数组的索引之后,会迭代链表,调用equals()方法检查key的相等性,如果equals()方法返回true,get方法返回Entry对象的value,否则,返回null。

四. ArrayList Vector LinkedList的 区别?

典型回答:

这三者都是实现集合框架中的List,也就是所谓的有序集合,因此具体功能也比较类似,比如都提供按照位置进行定位添加或者删除的操作,都提供迭代器以遍历其内容等。但因为具体的设计区别在行为性能线程安全等方面,表现又有很大不同。

Vector是Java早期提供的线程安全的动态数组,如果不需要线程安全,并不建议选择,毕竟同步是有额外开销的。Vector内 部是使用对象数组来保存数据,可以根据需要自动的增加容量,当数组以满时,会创建新的数组,并拷贝原有数组数据。

ArrayList是应用更加广泛的动态数组实现,它本身不是线程安全的,所以性能要好很多。与Vector近似,ArrayList也是可以根据需要调整容量,不过两者的调整逻辑有所区别, Vector在扩容时会提高1倍,而ArrayList则是增加50%。

LinkedList顾明思议是Java提供的双向链表,所以它不需要像.上面两种那样调整容量,它也不是线程安全的。

Vector和ArrayList作为动态数组,其内部元素以数组形式顺序存储的,所以非常适合随即访问的场合。除了尾部出入元素和删除元素,往往性能会相对较差,比如我们在中间位置插入一个元素,需要移动后续所有元素。而LinkedList进行节点插入删除却要高效得很多,但是随即访问性能则要比动态数组慢。


本文转载自:今日份阿里Java后端面试真题,看完你学会了嘛?附面试福利


推荐阅读
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • 设计模式——模板方法模式的应用和优缺点
    本文介绍了设计模式中的模板方法模式,包括其定义、应用、优点、缺点和使用场景。模板方法模式是一种基于继承的代码复用技术,通过将复杂流程的实现步骤封装在基本方法中,并在抽象父类中定义模板方法的执行次序,子类可以覆盖某些步骤,实现相同的算法框架的不同功能。该模式在软件开发中具有广泛的应用价值。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了源码分析--ConcurrentHashMap与HashTable(JDK1.8)相关的知识,希望对你有一定的参考价值。  Concu ... [详细]
  • Python15行代码实现免费发送手机短信,推送消息「建议收藏」
    Python15行代码实现免费发 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • EzPP 0.2发布,新增YAML布局渲染功能
    EzPP发布了0.2.1版本,新增了YAML布局渲染功能,可以将YAML文件渲染为图片,并且可以复用YAML作为模版,通过传递不同参数生成不同的图片。这个功能可以用于绘制Logo、封面或其他图片,让用户不需要安装或卸载Photoshop。文章还提供了一个入门例子,介绍了使用ezpp的基本渲染方法,以及如何使用canvas、text类元素、自定义字体等。 ... [详细]
  • centos安装Mysql的方法及步骤详解
    本文介绍了centos安装Mysql的两种方式:rpm方式和绿色方式安装,详细介绍了安装所需的软件包以及安装过程中的注意事项,包括检查是否安装成功的方法。通过本文,读者可以了解到在centos系统上如何正确安装Mysql。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 在IDEA中运行CAS服务器的配置方法
    本文介绍了在IDEA中运行CAS服务器的配置方法,包括下载CAS模板Overlay Template、解压并添加项目、配置tomcat、运行CAS服务器等步骤。通过本文的指导,读者可以轻松在IDEA中进行CAS服务器的运行和配置。 ... [详细]
author-avatar
dvs5453401
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有