毕业论文
您现在的位置: 语言识别 >> 语言识别资源 >> 正文 >> 正文

全面的高质量Android面试指南

来源:语言识别 时间:2023/5/16
北京正规湿疹医院 http://m.39.net/disease/a_9092469.html

数据结构与算法

数据结构与算法问题的难度完全取决于你所申请的公司

数组

数组由一组相同的数据类型组成。它存储在连续的内存空间内,使用索引可以找到元素的地址。数组包括一维数组和多维数组,一维数组是最简单的数据结构,也是最常用的。

链表

链表看起来更像树,而不是数组,它使用一组结点来表示一个序列。每一个结点都包含数据和一个指针。在链表中,结点中的数据可以为任意类型,而指针则是指向下一结点的引用。链表包含一个头结点和一个尾结点。头结点是链表中的第一个结点,尾结点是最后一个结点。链表不是一个循环数据结构,所以尾结点没有指向头结点的指针,指针为空。一些基础方法的时间复杂度如下:

双向链表

一个双向链表首先是一个链表,但是在每个结点中有两个指针,前驱指针指向前驱结点,后继指针指向后继结点。双向链表也有一个头结点,头结点的后继指针指向第一个结点。最后一个结点的后继指针指向空,但是如果最后一个结点的后继指针指向第一个结点,这时称这个链表为双向循环链表。双向循环链表能非常方便地从每个结点查找它的前驱结点和后继结点。

栈是一个有着「后进先出」特性的基础数据结构,这就意味着最后一个入栈的元素,也是第一个出栈的。栈就像是一堆书,想要得到书堆中的第一本书(最下面一本),必须把其他的书都先拿走。向栈中添加一个元素的操作被称为Push(入栈),删除一个元素的操作被称为Pop(出栈),查看且不删除最后一个入栈的元素的操作被称为Top。实现栈的常用方法是使用链表(LinkdList),也可以使用不允许空值的StackArray(使用数组实现),还有允许空值的Vctor

贪心算法

所谓贪心算法(贪婪算法),是在求解一个问题时,作出当前最好的选择,而不考虑大局。也就是说,这种算法的每一种实现,只是在作出一个某种方面上的局部最优解。

我们可以说贪心算法是「短视的」,「不可恢复」的

此算法没有固定框架,只有每个人贪心策略的选择,而导致的不同姿态的代码实现。

来自wikipdia:

贪心法,又称貪心演算法、貪婪演算法、或稱貪婪法,是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。[1]比如在旅行推销员问题中,如果旅行员每次都选择最近的城市,那这就是一种贪心算法。

贪心算法在有最优子结构的问题中尤为有效。最优子结构的意思是局部最优解能决定全局最优解。简单地说,问题能够分解成子问题来解决,子问题的最优解能递推到最终问题的最优解。

贪心算法与动态规划的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。

贪心法可以解决一些最优化问题,如:求图中的最小生成树、求哈夫曼编码……对于其他问题,贪心法一般不能得到我们所要求的答案。一旦一个问题可以通过贪心法来解决,那么贪心法一般是解决这个问题的最好办法。由于贪心法的高效性以及其所求得的答案比较接近最优结果,贪心法也可以用作辅助算法或者直接解决一些要求结果不特别精确的问题。

Java核心

解释一下OOP的概念

面向对象编程是使用类,对象,继承性,多态性,封装性和抽象的一种程序设计方法。。

抽象

在面向对象的概念中,所有对象都是由类来描述,但是反过来,并不是所有类都是用来描述对象的。如果一个类中没有包含足够信息来描绘一个具体的对象,这样的类就是抽象类。

继承

继承(英语:inhritanc)是面向对象软件技术当中的一个概念。如果一个类别A“继承自”另一个类别B,就把这个A称为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。一般静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充。有些编程语言支持多重继承,即一个子类别可以同时有多个父类别,比如C++编程语言;而在有些编程语言中,一个子类别只能继承自一个父类别,比如Java编程语言,这时可以利用接口来实现与多重继承相似的效果。现今面向对象程式设计技巧中,继承并非以继承类别的“行为”为主,而是继承类别的“型态”,使得元件的型态一致。另外在设计模式中提到一个守则,“多用合成,少用继承”,此守则也是用来处理继承无法在执行期动态扩充行为的遗憾。

封装

从字面上理解就是包装的意思,是指利用抽象数据类型,将数据和关于数据的操作封装起来,使其成为一个不可分割的独立实体。数据将会被保护在抽象数据类型的内部,仅能够通过暴露在表面的操作(public方法,比如sttr和gttr)来与这个对象进行交流和交互。用户不知道对象的内部细节,但是通过该对象提供的接口来访问对象。其好处是:减少耦合,方便地在未来修改调整自己,更加有把握地(精确地)控制成员,隐藏信息,实现细节。

多态

使用相同的消息,使得类作出不同的反应(继承为我们使用多态打下了基础)。Java实现多态有三个必要条件:继承、重写、向上转型。

面向对象的三个基本元素和五个原则

三个基本元素

封装:封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。

多态:多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。

五个基本原则

单一职责原则(Singl-RsposibilityPrincipl):一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。

开放封闭原则(Opn-Closdprincipl):软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。

Liskov替换原则(Liskov-SubstituionPrincipl):子类必须能够替换其基类。这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。

依赖倒置原则(Dpndcy-InvrsionPrincipl):依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。

接口隔离原则(Intrfac-SggationPrincipl):使用多个小的专门的接口,而不要使用一个大的总接口。

抽象类和接口的区别?Link

抽象类是一个可同时包含具体方法和抽象方法(方法未被实现)的类。抽象方法必须被该抽象类的子类实现。抽象类是可以继承的。接口像是描述类的一张蓝图或者说是类的一种契约,它包含了许多空方法,这代表着它的所有的子类都应该拥有共同点。它的子类应该提供这些空方法的具体实现。一个类需要用implmnts来实现接口,接口可以用xtnds来继承其他接口。在设计层级理解他们的不同:

抽象的层次不同:抽象类对类的整体(包括属性,行为)都可以进行抽象,接口对类的局部进行抽象,具体来说接口仅仅是对类的行为进行抽象。跨域不同:抽象类是从各种子类中提取相似的部分,然后泛化成抽象类,子类可以继承这样的抽象类。实现接口是不存在is-a的关系的类们,你不可以称同样可以飞行的飞机和鸟为同一个抽象类,但是他们可以有同样的接口fly-abl。抽象类的父类和派生类在概念上一致,接口的原生类和派生类在仅仅在局部行为上一致。设计层次不同:抽象类是从一堆在底层的子类们来进行抽象提取,从下往上,从而产生抽象类;接口是在直接定义的高度来声明的,然后从这个高度上往下实现此接口。抽象类是自底向上抽象而来的,接口是自顶向下设计出来的。

序列化是什么?如何实现它?

序列化是一种将对象转换为字节流的过程,目的是为了将该对象存储到内存中,等后面再次构建该对象时可以获取到该对象先前的状态及数据信息。Java中,有两种方式可以实现序列化,既可以实现Srializabl接口,也可以实现Parclabl接口。然而,在Android中,我们不应该使用Srializabl接口。因为Srializabl接口使用了反射机制,这个过程相对缓慢,而且往往会产生出很多临时对象,这样可能会触发垃圾回收器频繁地进行垃圾回收。相比而言,Parclabl接口比Srializabl接口效率更高,性能方面要高出10x多倍。

什么是单例?

单例模式指的是一个类只能被初始化一次,即只有一个实例。单例模式限定一个类只能拥有一个实例。这在系统中只需要一个实例来和其他模块协调工作时是很实用的。单例普遍使用在只需要一个或是限制一定数量实例的系统中。(wikipdia)

什么是匿名内部类?

普通的类可以自然地实例化他自己,相反地,内部类是这样的类:一定要绑定上一个外部类才能进行实例化的类。

内部类提供了一种模拟车和车轮的机制,车是外部类,车轮是内部类

而匿名内部类也就是没有名字的内部类,因为没有名字,所以只能使用一次。

使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口

详情可见:   当打开一个新的屏幕时,之前一个屏幕会被置为暂停状态,并且压入历史堆栈中。用户可以通过回退操作返回到以前打开过的屏幕。可以选择性的移除一些没有必要保留的屏幕,因为Android会把每个应用的开始到当前的每个屏幕保存在堆栈中。

服务

Srvic是android系统中的一种组件,它跟Activity的级别差不多,但是他不能自己运行,只能后台运行,并且可以和其他组件进行交互。Srvic是没有界面的长生命周期的代码。Srvic是一种程序,它可以运行很长时间,但是它却没有用户界面。这么说有点枯燥,来看个例子。

打开一个音乐播放器的程序,这个时候若想上网了,那么,打开Android浏览器,这个时候虽然已经进入了浏览器这个程序,但是,歌曲播放并没有停止,而是在后台继续一首接着一首的播放。其实这个播放就是由播放音乐的Srvic进行控制。

当然这个播放音乐的Srvic也可以停止,例如,当播放列表里边的歌曲都结束,或者用户按下了停止音乐播放的快捷键等。Srvic可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录地理信息位置的改变等等,总之服务嘛,总是藏在后头的。

开启Srvic有两种方式:

Contxt.startSrvic()

Srvic会经历onCat-onStart(如果Srvic还没有运行,则android先调用onCat()然后调用onStart();      如果Srvic已经运行,则只调用onStart(),所以一个Srvic的onStart方法可能会重复调用多次);

StopSrvic的时候直接onDstroy,如果是调用者自己直接退出而没有调用StopSrvic的话,Srvic会一直在后台运行。该Srvic的调用者再启动起来后可以通过stopSrvic关闭Srvic。   *注意:多次调用Contxt.startsrvic()不会嵌套(即使会有相应的onStart()方法被调用),所以无论同一个服务被启动了多少次,一旦调用Contxt.stopSrvic()或者StopSlf(),他都会被停止。   补充说明:传递给StartSrvic(0的Intnt对象会传递给onStart()方法。调用顺序为:onCat--onStart(可多次调用)--onDstroy。

Contxt.bindSrvic()

Srvic会经历onCat()--onBind(),onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Srvic运行的状态或其他操作。这个时候把调用者(Contxt,例如Activity)会和Srvic绑定在一起,Contxt退出了,Svic就会调用onUnbind--onDstroyd相应退出,所谓绑定在一起就共存亡了。

广播接收器

在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制。而BroadcastRcivr是对发送出来的Broadcast进行过滤接受并响应的一类组件。可以使用BroadcastRcivr来让应用对一个外部的事件做出响应。这是非常有意思的,例如,当电话呼入这个外部事件到来的时候,可以利用BroadcastRcivr进行处理。

例如,当下载一个程序成功完成的时候,仍然可以利用BroadcastRcivr进行处理。BroadcastRcivr不能生成UI,也就是说对于用户来说不是透明的,用户是看不到的。

BroadcastRcivr通过NotificationManagr来通知用户这些事情发生了。BroadcastRcivr既可以在AndroidManifst.xml中注册,也可以在运行时的代码中使用Contxt.gistrRcivr()进行注册。只要是注册了,当事件来临的时候,即使程序没有启动,系统也在需要的时候启动程序。各种应用还可以通过使用Contxt.sndBroadcast()将它们自己的IntntBroadcasts广播给其他应用程序。

内容提供者

ContntProvidr是Android提供的第三方应用数据的访问方案。

在Android中,对数据的保护是很严密的,除了放在SD卡中的数据,一个应用所持有的数据库、文件等内容,都是不允许其他直接访问的。Andorid当然不会真的把每个应用都做成一座孤岛,它为所有应用都准备了一扇窗,这就是ContntProvidr。应用想对外提供的数据,可以通过派生ContntProvidr类,封装成一枚ContntProvidr,每个ContntProvidr都用一个uri作为独立的标识,形如:contnt://

转载请注明:http://www.0431gb208.com/sjslczl/4625.html

  • 上一篇文章:
  • 下一篇文章: 没有了