2018面试总结

[toc]

2018面试总结

重载以及重写的区别:

重写(override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不可以改变。

规则

  • 参数列表必须与被重写方法相同
  • 返回类型必须与被重写方法相同
  • 访问权限不能比父类中被重写的方法的访问权限更低
  • 父类的成员方法只能被它的子类 重写
  • 声明为final的方法不能被重写
  • 声明为static的方法不能被重写,但是能够被再次声明
  • 子类和父类不在同一个包中,那么子类可以重写父类所有的方法,除了声明为final和private的方法之外
  • 子类和父类不在同一个包中,那么子类只能够重写父类的public和protected的非final方法
  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
  • 构造方法不可以被重写
  • 如果不能继承一个方法,则不能重写这个方法。

重载(Overload)
重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

规则

  • 被重载得方法必须改变参数列表(个数或者类型)
  • 被重载得方法可以改变返回类型
  • 被重载得方法可以改变访问修饰符
  • 被重载得方法可以声明或者更广得检查异常
  • 方法能够在同一个类中或者在一个子类中被重载
  • 无法以返回值类型作为重载函数的区分标准
区别点 重载overload 重写override
参数列表 必须修改 不可以修改
返回类型 可以修改 不可以修改
异常 可以修改 可以减少或者删除,一定不能抛出新的或者更广的异常
访问 可以修改 一定不能做更严格的限制(可以降低限制)
发生时期 编译期(在编译期就可以根据参数类型来选择运行哪个方法) 运行期(编译期在编译期并不知道要运行哪个方法,只有在代码运行的时候jvm才可以做出决定)

Service以及IntentService的区别

区别点 Service IntentService
运行线程 依附于主线程 自身内部新开了线程
是否是完整的生命周期

IntentService继承于Service,所以它有service的所有特性,也包括service的生命周期,与Service不同的是,IntentService在执行oncreate的时候,内部开辟了一个新线程,去执行所要执行的耗时操作,而普通的service是依赖于应用的主线程的,所以service事实上并不能做耗时操作(不开异步线程的话)
具体参考参考

区别点 Service IntentService
运行线程 依附于主线程 自身内部新开了线程
是否是完整的生命周期

线程间的通讯方式

  • runOnUiThread(Runnable)
  • View.postDelay(Runnable , long)/new Handler().postDelayed(Runnable)
  • Message/Handler
  • AsyncTask

进程间通信的方式

  • Bundle/Intent传递数据

可传递基本类型,String,实现了Serializable或Parcellable接口的数据结构。Serializable是Java的序列化方法,Parcellable是Android的序列化方法,前者代码量少(仅一句),但I/O开销较大,一般用于输出到磁盘或网卡;后者实现代码多,效率高,一般用户内存间序列化和反序列化传输。

  • 文件共享:

对同一个文件先后写读,从而实现传输,Linux机制下,可以对文件并发写,所以要注意同步。顺便一提,Windows下不支持并发读或写。

  • Messenger:

Messenger是基于AIDL实现的,服务端(被动方)提供一个Service来处理客户端(主动方)连接,维护一个Handler来创建Messenger,在onBind时返回Messenger的binder。双方用Messenger来发送数据,用Handler来处理数据。Messenger处理数据依靠Handler,所以是串行的,也就是说,Handler接到多个message时,就要排队依次处理。

  • AIDL:

AIDL通过定义服务端暴露的接口,以提供给客户端来调用,AIDL使服务器可以并行处理,而Messenger封装了AIDL之后只能串行运行,所以Messenger一般用作消息传递。通过编写aidl文件来设计想要暴露的接口,编译后会自动生成响应的java文件,服务器将接口的具体实现写在Stub中,用iBinder对象传递给客户端,客户端bindService的时候,用asInterface的形式将iBinder还原成接口,再调用其中的方法。

  • ContentProvider:

系统四大组件之一,底层也是Binder实现,主要用来为其他APP提供数据,可以说天生就是为进程通信而生的。自己实现一个ContentProvider需要实现6个方法,其中onCreate是主线程中回调的,其他方法是运行在Binder之中的。自定义的ContentProvider注册时要提供authorities属性,应用需要访问的时候将属性包装成Uri.parse(“content://authorities”)。还可以设置permission,readPermission,writePermission来设置权限。 ContentProvider有query,delete,insert等方法,看起来貌似是一个数据库管理类,但其实可以用文件,内存数据等等一切来充当数据源,query返回的是一个Cursor,可以自定义继承AbstractCursor的类来实现。

  • Socket:

学过计算机网络的对Socket不陌生,所以不需要详细讲述。只需要注意,Android不允许在主线程中请求网络,而且请求网络必须要注意声明相应的permission。然后,在服务器中定义ServerSocket来监听端口,客户端使用Socket来请求端口,连通后就可以进行通信。

  • 广播(Broadcast)

广播是一种被动跨进程通讯的方式。当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据。这就象电台进行广播一样,听众只能被动地收听,而不能主动与电台进行沟通。 在应用程序中发送广播比较简单。只需要调用sendBroadcast方法即可。该方法需要一个Intent对象。通过Intent对象可以发送需要广播的数据。

ArrayList以及LinkList的区别

相同点

  1. 都是List接口的实现类,所以都实现了List的所有未实现的方法(面向接口开发,List->Collection->Iterable)

不同点

  1. ArrayList实现了List接口,是以数组的形式来进行实现的,所以可以很方便地使用索引的方法来快速定位对象的位置(所以对于要求快速取得对象的需求,用ArrayList更加方便
  2. LinkedList是使用链表的方式来进行实现的,他本身有自己的对应方法:addFirst(),addLast()等等,由于是采用链表的方式实现的,所以在insert,remove的时候要比ArrayList方便快捷得多,适合用来实现Stack(堆栈)Queue(队列)

问题

  1. 在删除和插入数据的时候,为什么ArrayList的效率会比较低呢?
    答:因为ArrayList是使用数组实现的,如果要从数组中插入或者删除一个对象,需要移动后半部分的元素,从而需要重新调整索引顺序,而这个需要耗费一定时间,所以速度上就慢了很多;而LinkedList是使用链表实现的,如果要从链表中删除或者插入一个数据对象,只需要改变前后对象的引用就可以了。

数组,ArrayList的区别

相同点

ArrayList是基于数组实现的,所以理论上ArrayList包含了数组的所有方法

不同点

  1. 数组可以包含基本数据类型和对象类型,ArrayList只能包含对象类型
  2. 数组的大小是固定的,而ArrayList是可以扩容的(扩容1.5倍)---> 在添加数据的时候,ArrayList会去检查是否超过了他的存储临界点,如果是超过了,那么他会自我扩容:创建新的内部数组(长度为老数组的1.5倍),把老的数据copy进去,再销毁老的数组。
  3. ArrayList通过拓展api提供了更多的方便api供开发者使用
  4. 对于基本数据类型,ArrayList使用自动封箱来减少编码工作量,但是,如果数据的长度是固定的话,这种方式比数组更慢(因为数据的长度已经固定了,数组的大小也可以确定了)

ArrayList和Vector的区别

同步性

Vector是线程安全的(同步的),而ArrayList是线程不安全的(不同步的)

操作

Vector支持多线程操作,所以在效率上比不上ArrayList

数据增长

ArrayList和Vector都有一个初始的容量大小,当存储进去它们里面的元素个数超出容量的时候,就需要增加ArrayList和Vector的存储空间,每次增加存储空间的时候不是只增加一个存储单元,是增加多个存储单元。
Vector默认增加原来的一倍,ArrayList默认增加原来的0.5倍。
Vector可以由我们自己来设置增长的大小,ArrayList没有提供相关的方法。

Android事件分发的原理

具体概况

将点击事件(MotionEvent)传递到某个具体的View & 处理的整个过程

参与角色

类型 简介 备注
Activity 控制生命周期&处理事件(Controller) 统筹视图的添加&显示;通过其他回调方法与window,view进行交互
View 所有UI组件的基类 基本上所有的视图都是继承自View
ViewGroup 一组View的集合 其本身也是View的子类;是安卓所有布局的父类;它实质上也是一个View,但是比普通的View多了包含子View&定义布局参数的功能

事件类型

方法 作用 调用时刻
dispatchTouchEvent() 分发&传递点击事件 当事件能够传递给当前View的时候,该方法就会被调用
onInterceptTouchEvent() 判断是否拦截了某个事件(该方法只存在于ViewGroup中,普通的View没有这个方法) 在ViewGroup的dispatchTouchEvent()中被调用
onTouchEvent() 处理点击事件 在dispatchTouchEvent()中被调用

事件流程

2018面试总结_第1张图片
偷来的示意图

equals以及hashcode

相同点

equals以及hashcode在java中的作用都是一样的,都是用于判断2个对象是否一致。

不同点

方法 好处 坏处
equals 比较全面,比较复杂 效率比较低
hashcode 单纯生成一个hashcode进行比较即可,效率更高 不同对象可能会生成一样的hashcode,所以这个单纯的比较并不是特别可靠

解决方案

由于他们2个分别存在有这样那样的问题,单纯用equals比较效率太低,单纯用hashcode去比较的话准确率太低,所以我们得出一个解决方案:
用这2个一起去比较!综合起来使用:需要比较的时候,我们先用hashCode()比较,如果hashCode()不一致了,那么这2个对象肯定不一致了,便无须进行equals()的比较了;反之即再进行equals()的比较,这样在保证稳定准确的前提下提高了效率。
这也是为什么我们重写了equals方法就一定要重写另外一个hashcode方法的原因了。

你可能感兴趣的:(2018面试总结)