怎么拿下Android开发面试题(二)
1.3 请简述一下String、StringBuffer和StringBuilder的区别?
1.String为字符串常量,StringBuffer与StringBuilder字符串变量,从而效率:
3.String2.StringBuffer1.StringBuilder(一般情况下);
2.StringBuffer是线程安全的,而StringBuilder为非线程安全;3.String是不可变的对象,每次对String类型进行改变的等同于生成了一个新的String对象,经常改变内容的字符串不建议使用String;
4.对StringBuffer类改变,每次结果都会对StringBuffer对象本身进行操作,而不是生成新的对象,再改变对象引用,经常改变内容的字符串建议使用StringBuffer;
5.StringBuffer上的主要操作为append和insert方法。
1.4 “equals”与“==”、“hashCode”的区别和使用场景?
(1)==:用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据(注意是基本类型)或两个引用变量是否相等,只能用 == 操作符。
假如一个变量指向的数据是对象类型的,例如Objet
obj1=newObject()那么,这时候涉及了两块内存;变量obj1是一个内存,newObject()是另一个内存(堆内存),此时,变量obj1所对应的内存中存储的数值就是对象占用的那块内存(堆内存)的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用 == 操作符进行比较;
(2)equals:
equals方法是用于比较两个独立对象的内容是否相同:
Stringa=newString("a");
Stringb=newString("a");
两条new语句创建了两个对象,然后用a和b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值(对应对象的首地址)是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。
(3)hashCode(hashCode就是对象的散列码,是根据对象的某些信息推导出的一个整数值,默认情况下表示是对象的存储地址,采用哈希算法(散列算法)来提高从集合中查找元素的效率,将数据按特定算法直接分配到不同区域上。):
因为重写的equals()里一般比较的比较全面比较复杂,这样效率就比较低,而利用hashCode()进行对比, 则只要生成一个 hash 值进行比较就可以了,hashCode效率很高,那么为什么还要用equals呢?
使用场景:
因为他们生成的hashCode()并不是完全可靠,有时候不同的对象也会一样(hash冲突),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠,所以可以得出:
- equals()相等的两个对象他们的hashCode()肯定相等,也就是用equals()对比是绝对可靠的。
- equals()相等的两个对象他们的hashCode()不一定
相等,也就是hashCode()不是绝对可靠的。
所有对于需要大量并且快速的对比的话如果都用equals()效率太低。所以需要对比的时候,首先用 hashCode() 去对比,如果hashCode() 不一样,则表示这两个对象肯定不相等(也就是不必再用 equals() 去再对比了),如果hashCode() 相同,此时再对比他们的 equals(),如果
equals() 也相同,则表示这两个对象是真的相同了!
1.5 Java 中深拷贝与浅拷贝的区别?
首先需要明白,浅拷贝和深拷贝都是针对一个已有对象的操作。那先来看看浅拷贝和深拷贝的概念。
在 Java中,除了基本数据类型(元类型)之外,还存在 类的实例对象 这个引用数据类型。而一般使用 『 = 』号做赋值操作的时候。
对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。
而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。
反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。
所以到在,就应该了解了,所谓的浅拷贝和深拷贝,只是在拷贝对象的时候,对类实例对象这种引用数据类型的不同操作而已。
总结来说:
1、浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
2、深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
1.6 谈谈Error和Exception的区别?
Exception是java程序运行中可预料的异常情况,咱们可以获取
到这种异常,并且对这种异常进行业务外的处理。
Error是java程序运行中不可预料的异常情况,这种异常发 生
以后,会直接导致JVM不可处理或者不可恢复的情况。所 以这
种异常不可能抓取到,比如OutOfMemoryError、NoClassDefFoundError等。其中的Exception又分为检查性异常和非检查性异常。两个根本
的区别在于:
检查性异常 必须在编写代码时,使用try catch捕获(比如:IOException异常)。
非检查性异常在代码编写时,可以忽略捕获操作( 比ArrayIndexOutOfBoundsException),这种异常是在代码编写
或者使用过程中通过规范可以避免发生的。
切记,Error是Throw不是Exception 。
1.7 什么是反射机制?反射机制的应用场景有哪些?
Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。
应用场景:
序列化和反序列化
:反射可以用于将对象转换为字节流(序列化)或从字节流中恢复对象(反序列化)。通过反射,可以动态地检查对象的属性和方法,并将其转换为字节流进行存储或传输。动态代理
:反射可以用于创建动态代理对象,这在 AOP(面向切面编程)和代理模式中很常见。动态代理对象可以在运行时拦截和处理方法调用,从而实现横切关注点的功能。单元测试
:反射可以用于单元测试框架,通过反射可以访问和调用私有方法、设置私有字段的值,以及执行其他测试所需的操作。
1.8 Java 中IO流分为几种?
Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。
Java中其他多种多样变化的流均是由它们派生出来的. 字符流和字节流是根据处理数据的不同来区分的。字节流按照8位传输,字节流是最基本的,所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。
- 字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串;
- 字节流提供了处理任何类型的IO操作的功能,但它不能
直接处理Unicode字符,而字符流就可以。
读文本的时候用字符流,例如txt文件。读非文本文件的时候用字节流,例如mp3。理论上任何文件都能够用字节流读取,但当读取的是文本数据时,为了能还原成文本你必须再经过一个转换的工序,相对来说字符流就省了这个麻烦,可以有方法直接读取。
字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节, 操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!
应用场景:
字节流:字节流主要用于处理二进制数据,如图像、音频、视频文件等。它们以字节为单位进行读写,适合处理任何类型的数据,包括文本数据。字节流通常使用InputStream和OutputStream类。
字符流:字符流用于处理文本数据,以字符为单位进行读写。它们在内部使用编码方式来处理字符数据,可以很好地处理各种字符集。字符流通常使用Reader和Writer类。
1.9 BIO、NIO、AIO 有什么区别
BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统IO,它的特点是模式简单使用方便,并发处理能力低。
NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
BIO是一个连接一个线程。
NIO是一个请求一个线程。
AIO是一个有效请求一个线程。
BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理 。
AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
适用场景分析
(1)BIO方式适用于连接数目比较小且固定的架构,这种方 式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
(2)NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
(3)AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。