三天时间整理了一些java/Android相关问题简述

1.内部类,静态内部类,匿名内部类是什么,他们的区别是什么?
答:在java中将一个类定义在另一个类或者一个方法里面,这样的类成为是内部类,广义上内部类一共是四种,成员内部类,局部内部类,匿名内部类和静态内部类。
成员内部类:最普通的内部类,定义在一个类的内部,成员内部类可以无条件的访问外部类的成员,但是外部类要想访问内部类的成员,必须要先创建一个成员内部类的对象,通过对象来引用。要创建一个成员内部类的对象,必须要有外部类的对象来创建。
局部内部类:定义在一个方法或者一个作用域里面的 类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者作用域内,局部内部类就像是方法里面的一个局部变量一样是不能有public等这样的修饰符。
匿名内部类:在编写事件监听的代码时候使用匿名内部类不但方便,而且让代码更加的容易维护。例如下面的OnClickListener就是一个匿名内部类,使用匿名内部类能够在实现父类或者接口中的方法情况下同时产生一个相应的对象,但是前提是这个父类必须先存在才能这样做。匿名内部类是没有构造器的,正是因为这样所以使用的范围十分的有限,大部分匿名内部类是用于接口的回调,匿名内部类用于继承其他类或者实现接口 ,并不需要增加额外的方法,只是对继承方法的实现或者重写。同样匿名内部类也不能有访问的修饰符。
  history_bt.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub 
            }
        });
静态内部类:定义在一个类里面的类,只不过是在类的前面加了关键字static。静态内部类是不需要以来于外部类的,这点和类的静态成员属性有点类似。并且它不能使用外部类的非static成员,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依赖于具体的对象。

2.Surfaceview和view的区别是什么?
答:view是在UI线程中去更新,但是surfaceview是在一个单独的子线程中去跟新。在UI线程中一旦时间长就会出现问题,所以在一些动画或者渲染的过程中是一个比较耗时的操作,就需要用到surfaceview,这样不会阻塞主线程。性能更好。
3.Android中进程的优先级?
答:五种进程按优先级依次排列为:前台进程(用户直接交互的进程),可见进程(没有任何的前景组件,但是会影响到用户所看到的屏幕上),服务进程(开启的一个服务),后台进程,空进程。
4.Asynctask原理
答:在Android中我们通过thread+handler实现多线程的通信,一种经典的 应用场景是在新线程中进行好事操作,当任务完成之后通过handler想主线程发送message,这样主线程的handler在收到message之后就可以进行更新ui的操作,在上面的场景之中分别在thread和handler中编写逻辑代码,未来使得代码更加统一,我们可以使用asynctask类。这个类在Android中是一个助手类,对thread和handler进行了封装,方便我们使用,方便我们在后台线程中执行操作,然后将结果发送给主线程,从而在主线程中进行ui更新等操作。使用asynctask操作时,我们不需要关注thread和handler,asynctask会对其进行管理,我们只需要关注自己的逻辑就可以。Asynctask有四种重要的回调方法,分别是:onPreExecute、doInBackground, onProgressUpdate 和 onPostExecute。我们通过调用asynctask的execute方法传入参数并执行任务,然后会依次调用这四个方法:
onPreExecute:这个方法有mainthread注解,标识这个方法是运行在主线程中的,在asynctask执行了execute方法之后就会在ui线程上执行这个方法,这个方法是在task真正执行前运行,我们通常可以在该方法中显示一个进度条告知用户后台任务即将开始
doInBackground:该方法有workerthread注解,标识这个方法是在单独的工作线程中,不是在主线程中,该方法在onpreexecute方法之后执行,用来在工作线程中执行耗时任务,我们可以在方法中编写我们需要在后台线程中运行的逻辑代码。由于运行在工作线程中,所以不会阻塞ui线程。在该方法中执行的后台任务可能会分解成多个步骤完成,没完成一个步骤可能需要将这个阶段性的结果发给主线程,那么就需要调用asynctask的publishProgress方法,处理结果传给主线程之后,会回调onProgressUpdate 方法,当然在doinbackground方法中也不可以不调用或者多次调用publishProgress方法。
onProgressUpdate :该方法也有 mainthread注解,标识是在主线程上被调用的,如果在doinbackground中多次调用了publishProgress方法,那么主线程就会多次回调onProgressUpdate 。
onPostExecute:该方法也有mainthread注解,表示该方法也是在主线程中被调用的,当doInBackground方法执行结束之后标识任务完成了,doInBackground方法的返回值就会作为参数在主线程中传入到onPostExecute中,这样就可以在主线程中根据任务的执行结果跟新ui。
5.序列化
答:序列化就是一种用来处理对象流的机制,所谓对向流就是将对象的内容进行流化,可以对流化后的对象进行读写操作,也可以对流化后的对象传输与网络之间。Serializable(来自java,操作很简单)和parcelable(来自Android,操作复杂,但是性能更好)两个接口可以完成序列化的过程。当需要使用intent和binder传输数据的时候就需要使用这两种序列化方式,还有需要对象持久化到存储设备或者通过网络传输给其他客户端,也需要用序列化。
6.集合
答:java中的集合类型主要是三种大类set,list,map,都是来源于数组,对数组的进一步封装,但是性能效率是不如数组的,但是功能比数据更加的丰富。
Set:不允许有相同的元素,不按特定的方式进行排序。主要的实现类型有hashset和treeset
,其中hashset的值根据hashcode的值来决定对象在hashset中的存储位置,treeset可以确保集合元素处在排序状态。
List:元素以线性方式存储,集合中可以存放重复对象,主要有两种实现类arraylist和linkedlist,其中arraylist代表长度可以改变的数组,可以对元素进行快速的随机的访问,插入删除速度比较慢,linkedlist采用链式结构,随机访问的速度比较慢,但是插入和删除的开销不大。addFirst(), addLast(), getFirst(), getLast(), removeFirst() 和 removeLast(), 这些方法 (没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。
map:是一种键值对集合,建对象不能重复,值对象是可以重复的。实现类主要是hashmap和treemap。Hashset使用hashcode进行快速查询,性能显著提高。Treemap特点在于得到的结果是经过排序的。
7.Hashmap是怎么实现的
答:在java中最基本的数据结构就是两种,一个是数组,另一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造,hashmap实际是一个链表散列的数据结构,就是数组和链表的结合体。Hashmap底层就是一个数组结构,数据中的每一项又是一个链表,当新建一个hashmap的时候就会初始化一个数组。简单地说,HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。
8.Ontouch和ontouchevent的区别是什么?如果重写了ontouch和onclick他们的调用顺序是怎么样?
答:首先ontouch方法是ontouchlistener接口中的方法,实现这个接口需要实现ontouch方法,通过view.setontouchlistener方法来使用。而ontouchevent是view的一个方法。明确的是ontouchlistener接口的优先级是逼ontouchevent高的,如果ontouchlistener中ontouch方法返回true标识事件已经被消费了,那么ontouchevent将不会再接受消息,如果返回是false那么会接着触发ontouchevent。
  先ontouch后onclick
在View中的dispatchTouchEvent方法中可以看到,是先执行OnTouchListener监听器中的onTouch方法,如果onTouchListener不为null,并且onTouch方法返回false的时候才执行onTouchEvent方法,如果我们把onTouch方法的返回值变成了true,onTouchEvent方法就不会执行。
OnClick的执行流程为:dispatchTouchEvent-->onTouch(返回为false)-->ViewGroup的onTouchEvent-->View的onTouchEvent-->在ACTION_UP的ACTION_UP时候performClick-->OnClick
当onTouch()方法返回为true;onTouchEvent方法就不执行了,OnClick方法就不执行了。

9.Android事件分发
答:说到事件分发,首先应该想到的是两个类,View和ViewGroup,ViewGroup是继承自View实现的,ViewGroup是控件容器,主要作用是包含具体控件,可以把ViewGroup想象成为一个盒子,里面按规则包含各种各样的控件,而包含控件的ViewGroup又可以把它当一个基本的控件单元,包含在另外一个ViewGroup中。实际上一个触摸事件是由上层的父类传递进来的,而最基本的ViewGroup的触摸事件则是由Activity传入的,Activity也有dispathTouchEvent()和onTouchEvent()方法,Activity接收到触摸事件时,会调用内部ViewGroup的dispathTouchEvent()方法。
事件分发流程和View相关的方法主要有两个:dispathTouchEvent()和onTouchEvent(), dispathTouchEvent()是分发事件的意思,onTouchEvent()才是真正处理事件的地方,实际上在View的dispathTouchEvent()方法中是通过调用onTouchEvent()处理事件的。在这里和触摸相关的还有一个onTouch方法,这个是使用控件的setOnTouchListene()设置的,它是满足一定条件时在onTouchEvent()方法之前调用的。
ViewGroup相关的方法除了dispathTouchEvent()和onTouchEvent(),还有一个onInterceptTouchEvent()方法,它表示的是拦截事件的意思,默认返回值是false,表示不拦截事件。
View调用顺序是:dispatchTouchEvent()->onTouch()->onTouchEvent()。
ViewGroup调用顺序:
dispatchTouchEvent()->onInterceptTouchEvent()->onTouch()->onTouchEvent()
ViewGroup的dispathcTouchEvent()返回true,代表关注该事件,后续的touch事件由它处理。
一个完成的触摸事件一般包括ACTION_DOWN,ACTION_MOVE,ACTION_UP等,ACTION_MOVE,ACTION_UP在一个触摸事件中不一定会出现。
ViewGroup的dispathTouchEvent()返回false,之后的action不会继续投递到该ViewGroup进行处理。这些action包括ACTION_MOVE,ACTION_UP等,直到下一次ACTION_DOWN事件出现.
 默认情况下dispatchTouchEvent(),onInterceptTouchEvent(),onTouchEvent()返回值都是false,表示不消费touch事件。
如果设置了View的clickable属性,那么onTouchEvent()返回true
返回值true表示关注此事件,如果一个View返回true,后续的事件都会分发给该View处理。
如果一个View返回false,表示不关注此事件,那么该事件后续的action比如ACTION_MOVE,ACTION_UP都不会分发给该View。

10.Java在运行main函数之前做了什么工作?
答:java类的执行顺序是:静态块(静态变量)——>成员变量——>构造方法——>静态方法 
1、静态代码块(只加载一次) 2、构造方法(创建一个实例就加载一次)3、静态方法需要调用才会执行
程序的执行顺序为: 
如果类还没有被加载: 
1、先执行父类的静态代码块和静态变量初始化,并且静态代码块和静态变量的执行顺序只跟代码中出现的顺序有关。 
2、执行子类的静态代码块和静态变量初始化。 
3、执行父类的实例变量初始化 
4、执行父类的构造函数 
5、执行子类的实例变量初始化 
6、执行子类的构造函数 
如果类已经被加载: 
则静态代码块和静态变量就不用重复执行,再创建类对象时,只执行与实例相关的变量初始化和构造方法。
那么main之前执行的就是静态块
11.Java中的静态方法能不能重写、
答:非静态方法属于类的实例,是可以被子类重写,从而达到多态的效果; 
静态方法属于类,是不能被重写,故而也不能实现多态。
12.为什么java静态方法不能调用普通方法,普通方法能调用静态方法
答:非静态方法和成员属于类的实例,只有在实例化之后才能使用,静态方法和属性属于类,静态的方法可以用类名加点的形式使用,如果一个静态方法以这种方式调用普通方法,此时实例对象是不存在的,那这个方法也不会存在,那么程序就会出错。
13.Java内存模式和GC机制
答:Java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程使用到的变量到主内存副本拷贝,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成。对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是可达的,哪些对象是不可达的.当GC确定一些对象为不可达时,GC就有责任回收这些内存空间。(不可达:没有其他对象再持有这个对象的引用)
14.Android中生命周期

如果是当前Activity弹出的dialog不会执行Activity任何生命周期中的方法,只有其它Activity弹出了Dialog或者拦住了当前的Activity才会执行onPause() 
启动Activity:系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态。
当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause方法,暂停当前Activity的执行。
当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。
当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。
用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。
当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。
用户退出当前Activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。
15.Android四大组件
答:activity:说白了就是一个一个的界面,用的最多,最直观。
broadcastreceiver:你的应用可以使用它对外部事件进行过滤只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity或serice 来响应它们收到的信息,或者用NotificationManager 来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
contentprovider:android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。这些数据可以存储在文件系统中、在一个SQLite数据库、或以任何其他合理的方式,其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据.(相当于在应用外包了一层壳),只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处:统一数据访问方式。
service:一个Service 是一段长生命周期的,没有用户界面的程序,可以用来开发如监控类程序。比较好的一个例子就是一个正在从播放列表中播放歌曲的媒体播放器。在一个媒体播放器的应用中,应该会有多个activity,让使用者可以选择歌曲并播放歌曲。然而,音乐重放这个功能并没有对应的activity,因为使用者当然会认为在导航到其它屏幕时音乐应该还在播放的。在这个例子中,媒体播放器这个activity 会使用Context.startService()来启动一个service,从而可以在后台保持音乐的播放。同时,系统也将保持这个service 一直执行,直到这个service 运行结束。另外,我们还可以通过使用Context.bindService()方法,连接到一个service 上(如果这个service 还没有运行将启动它)。当连接到一个service 之后,我们还可以service 提供的接口与它进行通讯。拿媒体播放器这个例子来说,我们还可以进行暂停、重播等操作。
16.Android启动模式,各自的应用场景
答:当我们多次启动同一个活动时,系统会创建多个实例,并把它们按照先进后出的原则一一放入任务栈中,当我们按回键时,就会有一个活动从任务栈顶移除,重复下去,直到任务栈为空,系统就会回收这个任务栈。但是这样以来,系统多次启动同一个活动时就会重复创建多个实例,这种做法显然不合理,为了能够优化这个问题,Android提供四种启动模式来修改系统这一默认行为。
一共有四种启动模式:
standard(标准启动模式):这个模式是默认的启动模式,即标准模式,在不指定启动模式的前提下,系统默认使用该模式启动活动,每次启动一个活动都会重写创建一个新的实例,不管这个实例存不存在, 。
singleTop:字面意思理解就是顶部只有一个,实际意义是如果某一个活动在栈顶,点击创建该活动的实例的时候那么该活动的实例就不会再被创建,顶部共享这一个,如果该实例不是在栈顶,那么需要创建的时候就要创建新的活动置于栈顶了。
singleTask:在这个模式下,如果栈中存在这个活动的实例就会复用这个活动,不管它是否位于栈顶,复用时,会将它上面的活动全部出栈,
singleInstance:该模式具备singleTask模式的所有特性外,与它的区别就是,这种模式下的活动会单独占用一个任务栈,具有全局唯一性,即整个系统中就这么一个实例,由于栈内复用的特性,后续的请求均不会创建新的活动实例,除非这个特殊的任务栈被销毁了。以singleInstance模式启动的活动在整个系统中是单例的,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。

17.Handler机制,多线程
答:在java中多线程的实现方式有多种,但是主要的方式就是两种,一种是继承自thread类重写run方法,另一种是实现runable接口(比较简单,就不多说了,这两种方式哦都是实现一个run方法)。在Android中对于多线程可以使用java自己的,当然还有Android自己独特的比如handler和looper。我认为handler在多线程中就是一个发送消息和处理消息的作用,每一个线程都会有一个消息队列,同时一个消息队列就会对应着一个handler。主线程对应的handler可以处理来自子线程传输过来的消息,用于ui更新等等。
  这里还涉及到一个looper,就是消息循环队列的意思,除了主线程的其他线程在新建的时候是没有消息循环队列的,想要建立就要自己添加。在多线程中,子线程run方法的结束线程就会自动关闭。这里还涉及到一个类是handlerThread,这也是一个线程,只不过是这个线程建立的时候就会自带消息循环队列。
18.Tcp建立链接三次握手,终止链接四次握手
答:建立链接:主机a向主机b发送SYN,主机b收到之后向A回复syn+ack,主机a收到之后回复ack,举个打电话的例子:
  A : 你好我是A,你听得到我在说话吗
  B : 听到了,我是B,你听到我在说话吗
  A : 嗯,听到了
  建立连接,开始聊天!
终止链接:主机a向b发送fin,主机b收到之后回复ack,之后主机b再向a发送fin+ack,主机a收到之后发送ack。举个打电话的例子:
A:“喂,我不说了。”
B:“我知道了。等下,上一句还没说完。Balabala…..”
B:”好了,说完了,我也不说了。”
A:”我知道了。”

19.http协议,HTTP协议和https区别
答:http协议工作原理:HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。
以下是 HTTP 请求/响应的步骤:
1、客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://www.oakcms.cn。
2、发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
3、服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
4、释放连接TCP连接
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
5、客户端浏览器解析HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

区别:超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此,HTTP协议不适合传输一些敏感信息,比如:信用卡号、密码等支付信息。
  为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS,为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。

20.Get请求和post请求
答:1.get请求的数据会附加到url之后,但是post请求数据会放在http请求的包体之内
    2.post请求的安全性更高
3.Post传输数据的量更大

21.排序算法,复杂度(O (nlogn)),快速排序
答:基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
22.Classloader的作用
答:ClassLoader的具体作用就是将class文件加载到jvm虚拟机中去,程序就可以正确运行了。但是,jvm启动的时候,并不会一次性加载所有的class文件,而是根据需要去动态加载。想想也是的,一次性加载那么多jar包那么多class,那内存不崩溃
23.Lrucache的底层实现
答:LRU(Least Recently Used)最近最少使用,它的核心思想是,如果一个数据被访问过,我们有理由相信它在将来被访问的概率就越高。于是当LRU缓存达到设定的最大值时将缓存中近期最少使用的对象移除。LRUCache内部使用LinkedHashMap来存储key-value键值对,并将LinkedHashMap设置为访问顺序来体现LRU算法。
Lrucache底层实际是维护的一个linkedHashMap集合(他是hashmap的一个子类,可以保证存入和取出顺序的集合,与hashmap不同的是他是一个双向链表,而haspmap是一个单向的链表结构),他有一个关键的方法就是在我们向lrucache中存储元素的时候,会先去将该元素所占空间大小与lrucache中所有元素的所占空间求和,然后和我们设置的最大可用存储内存进行比较,如果超过我们设置的最大值,就会将最近最少使用的元素删除以腾挪空间,每当我们获取元素时,会将原位置的元素进行删除,然后重新在表头将获取的元素进行插入。
24.Synchronzed,volatile的用法
答:首先说明的是,为了保证多线程操作中数据的一致性,才会使用这两个关键字,但是他们实际上还是有一些区别的。
volatile关键字:
有这样的现象,编译器为了加快程序运行的速度,对一些变量的写操作会先在寄存器或者是CPU缓存上进行,最后才写入内存.
而在这个过程,变量的新值对其他线程是不可见的.而volatile的作用就是使它修饰的变量的读写操作都必须在内存中进行!volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,
synchronized关键字:
synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.
1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
3.volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
4.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
5.volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化

25.自定义view有几个构造方法
答:在自定义组件中有三个方法,分别是onmeasure(确定自定义组件的尺寸大小),onlayout(确定各个子view的位置),ondraw(绘制自定义的组件)。自定义组件分成是自定义view和自定义viewgroup,自定义view中用到onmeasure和ondraw,自定义viewgroup中用到onmesrue和onlayout
26.Listview的convert view的作用是什么,用viewholder为什么可以优化他
答:我理解的convertview就是listview中item的布局视图。Viewhodler优化convertview的原理是,可以有效的避免每次在给item绑定数据的时候都要使用findviewbyid来定位到每一个控件,使用viewhoder时候就可以只查找布局文件一次,大大的提高了效率
27.Bitmap怎么避免oom
答:Android系统会为每个APP分配一个独立的工作空间,或说是分配一个单独的Dalcik虚拟机,这样每个APP就可以独立运行而不相互影响了。而Android对于每个Dalvik虚拟机都会有一个最大的内存限制,如果当前占用的内存加上我们申请的内存资源超过了这个限制,系统就会抛出OOM错误!对于Bitmap引起的OOM问题,可以采用以下两种方式解决:
1)采用低内存占用量的编码方式
在BitmapFactory.Options 这个类,我们可以设置下其中的inPreferredConfig属性,默认是 Bitmap.Config.ARGB_8888 ,我们可以修改成 Bitmap.Config.ARGB_4444
Bitmap.Config ARGB_4444:每个像素占四位,即A=4,R=4,G=4,B=4,那么一个像素点占4+4+4+4=16位
Bitmap.Config ARGB_8888:每个像素占八位,即A=8,R=8,G=8,B=8,那么一个像素点占8+8+8+8=32位
默认使用ARGB_8888,即一个像素占4个字节!
2)图片压缩
同样是BitmapFactory.Options,我们通过 inSampleSize 设置缩放倍数,比如写2,即长宽变为原来的1/2,图片就是原来的1/4,如果不进行缩放的话设置为1即可!
28.List和set区别
答:list可以存储相同的元素并且是有序的,set不能存储相同的元素同时是无序的
29.Recyclerview和listview还有scrollview的区别是什么,各自的缓存原理是什么
答:listview只能垂直滑动,但是recyclerview是可以横向和纵向滑动。对于性能优化中listviwe是没有viewholder的,需要自定义,但是recyclerview中是有的。
缓存的原理大致相同,但是也有所区别,离屏的ItemView即被回收至缓存,入屏的ItemView则会优先从缓存中获取,只是ListView与RecyclerView的实现细节有差异.同时listview只有两级缓存,recyclerview是四级缓存。(细节上的差异不详)
30.进程和线程的区别
答:进程:指在系统中能独立运行并作为资源分配的基本单位,它是由一组机器指令、数据和堆栈等组成的,是一个能独立运行的活动实体。
线程:线程是进程中的一个实体,作为系统调度和分派的基本单位
线程的性质:
1.线程是进程内的一个相对独立的可执行的单元。若把进程称为任务的话,那么线程则是应用中的一个子任务的执行。
2.由于线程是被调度的基本单元,而进程不是调度单元。所以,每个进程在创建时,至少需要同时为该进程创建一个线程。即进程中至少要有一个或一个以上的线程,否则该进程无法被调度执行。
3.进程是被分给并拥有资源的基本单元。同一进程内的多个线程共享该进程的资源,但线程并不拥有资源,只是使用他们。
4.线程是操作系统中基本调度单元,因此线程中应包含有调度所需要的必要信息,且在生命周期中有状态的变化。
5.由于共享资源【包括数据和文件】,所以线程间需要通信和同步机制,且需要时线程可以创建其他线程,但线程间不存在父子关系。
31.Hashcode和equals有什么关系
答:hashCode()和equals()的关系是这样的:
如果两个对象相等(equal),它们的hashcode一定相同;
如果两个对象有相同的hashcode,它们不一定相等(equal);
之所以这样设计是为了在Map中更快的查找到对象(相对于线性搜索);
一般Map都设计成数组+链表的结构,使用hashcode去查找对象需要两个步骤,首先使用hashcode定位数组下标索引,然后遍历该数组元素对应的链表,找到equals的元素;
Object默认的hashcode实现对于不同的对象会返回不同的值。值的散列就像在车库储存货物,不同的货物能被存放到不同的车库。比较有效查找货物办法是将不同的货物存到不同的车库中,而不是同一个车库;所以将hash值尽可能的分散是一个比较好的策略;
32.Final的作用
答:final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。 final方法不能被子类的方法覆盖,但可以被继承,如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。 使用final方法的原因有二: 第一、把方法锁定,防止任何继承类修改它的意义和实现。 第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。  用final修饰的成员变量表示常量,只能被赋值一次,赋值后值无法改变!一旦给final变量初值后,值就不能再改变了。 4、final参数 当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。 注:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。 final不能用于修饰构造方法。
33.Lambda表达式
答:() -> System.out.println("Hello Lambda Expressions");
(int even, int odd) -> even + odd
34.发送网络请求的过程
答:   HttpUrlConnection是JDK里提供的联网API,我们知道Android SDK是基于Java的,所以当然优先考虑HttpUrlConnection这种最原始最基本的API,其实大多数开源的联网框架基本上也是基于JDK的HttpUrlConnection进行的封装罢了,掌握HttpUrlConnection需要以下几个步骤:
1将访问的路径转换成URL。URL url = new URL(path);  
2,通过URL获取连接。HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
3,设置请求方式。 conn.setRequestMethod("GET");  
4,设置连接超时时间。 conn.setConnectTimeout(5000);  
5,设置请求头的信息。 
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");  
6,获取响应码 int code = conn.getResponseCode();  
7,针对不同的响应码,做不同的操作 
   7.1,请求码200,表明请求成功,获取返回内容的输InputStream is = conn.getInputStream();  
    7.2,将输入流转换成字符串信息 
35.Java中类加载的过程
答:类从被加载到JVM中开始,到卸载为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。
其中类加载过程包括加载、验证、准备、解析和初始化五个阶段。
加载:简单的说,类加载阶段就是由类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang.Class对象实例(Java虚拟机规范并没有明确要求一定要存储在堆区中,只是hotspot选择将Class对戏那个存储在方法区中),这个Class对象在日后就会作为方法区中该类的各种数据的访问入口。
(链接阶段要做的是将加载到JVM中的二进制字节流的类数据信息合并到JVM的运行时状态中,经由验证、准备和解析三个阶段。)
验证验证类数据信息是否符合JVM规范,是否是一个有效的字节码文件,验证内容涵盖了类数据信息的格式验证、语义分析、操作验证等。
格式验证:验证是否符合class文件规范
语义验证:检查一个被标记为final的类型是否包含子类;检查一个类中的final方法视频被子类进行重写;确保父类和子类之间没有不兼容的一些方法声明(比如方法签名相同,但方法的返回值不同)
操作验证:在操作数栈中的数据必须进行正确的操作,对常量池中的各种符号引用执行验证(通常在解析阶段执行,检查是否通过富豪引用中描述的全限定名定位到指定类型上,以及类成员信息的访问修饰符是否允许访问等)
准备为类中的所有静态变量分配内存空间,并为其设置一个初始值(由于还没有产生对象,实例变量不在此操作范围内)
被final修饰的静态变量,会直接赋予原值;类字段的字段属性表中存在ConstantValue属性,则在准备阶段,其值就是ConstantValue的值
解析将常量池中的符号引用转为直接引用(得到类或者字段、方法在内存中的指针或者偏移量,以便直接调用该方法),这个可以在初始化之后再执行。
可以认为是一些静态绑定的会被解析,动态绑定则只会在运行是进行解析;静态绑定包括一些final方法(不可以重写),static方法(只会属于当前类),构造器(不会被重写)
初始化将一个类中所有被static关键字标识的代码统一执行一遍,如果执行的是静态变量,那么就会使用用户指定的值覆盖之前在准备阶段设置的初始值;如果执行的是static代码块,那么在初始化阶段,JVM就会执行static代码块中定义的所有操作
36.MVC,MVP设计模式
答:MVP是模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块。 模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;视图(View):负责界面数据的展示,与用户进行交互;主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来。

MVC就是Model-View-Controller,它们的作用是:
(数据模型)Model:数据的封装和保存,业务逻辑和实体模型
(视图)View:视图界面,对应于布局文件
(控制器)Controller:业务逻辑,对应于Activity、Fragment等

37.Bundle的数据结构,如何存储
答:Bundle主要用于传递数据;它保存的数据,是以key-value(键值对)的形式存在的。
我们经常使用Bundle在Activity之间传递数据,传递的数据可以是boolean、byte、int、long、float、double、string等基本类型或它们对应的数组,也可以是对象或对象数组。当Bundle传递的是对象或对象数组时,必须实现Serializable 或Parcelable接口
38.Service是实现跨进程机制(binder?)
39.线程池的种类,
答:线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程。线程池中线程的数量通常完全取决于可用内存数量和应用程序的需求。然而,增加可用线程数量是可能的。线程池中的每个线程都有被分配一个任务,一旦任务已经完成了,线程回到池子中并等待下一次分配任务。线程池适用于单个任务处理时间很短,需要处理的任务数量比较大的情况。线程池一共是四种类型:
1、newFixedThreadPool创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。 
2、newCachedThreadPool创建一个可缓存的线程池。这种类型的线程池特点是: 
    1).工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。 
    2).如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。 
3、newSingleThreadExecutor创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的 。 

 4、newScheduleThreadPool创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。
40.http请求报结构,有几种contenttype,返回码的类型和区别
答:一个HTTP请求报文由四个部分组成:请求行、请求头部、空行、请求数据。
请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成
请求头部,客户端向服务器发送请求的时候必须指明请求类型(一般是GET或者 POST)。如有必要,客户程序还可以选择发送其他的请求头。大多数请求头并不是必需的,但Content-Length除外。对于POST请求来说 Content-Length必须出现。
空行它的作用是通过一个空行,告诉服务器请求头部到此为止。
请求数据,若请求方法字段是GET,则此项为空,没有数据。若方法字段是POST,则通常来说此处放置的就是要提交的数据

在Http请求中,我们每天都在使用Content-type来指定不同格式的请求信息,
text/html : HTML格式
    text/plain :纯文本格式      
    text/xml :  XML格式
    image/gif :gif图片格式    
    image/jpeg :jpg图片格式 
    image/png:png图片格式
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

HTTP错误主要分成三类:用户设备问题、Web服务器问题、连接问题。当客户端向Web服务器发送一个HTTP请求时,服务器都会返回一个响应代码。
HTTP状态码中定义了5大类
Informational
从 100到199范围的HTTP状态码是信息报告码。
首先,如果一个浏览器尝试访问一个网站,而 网站返回这些代码时,它们往往都不会显示在屏幕上。它们只是浏览器使引用的内部码。另外,这些代码不常见的另外一个原因是起初HTTP标准不允许使用这一 范围的状态码。
Successful
从 200到299范围的状态码是操作成功代码。
这些代码是在浏览器内部使用的,用以确认操作成功确认和当前请求状态。虽然这些代码通常不显示,但是有一些故障排除工具能够读到它们,就像和其它大多数的HTTP状态码一样,它们在错误诊断过程中是非常有用的。
Redirection
从 300到399范围的状态码是重定向代码。
本质上,它们告诉Web浏览器必须执行其它一些操作以完成请求。基于这个命令的特点,它可以自动地执行,或者要求额外的用户输入。比如,状态码301表示一个特定资源已经被永久地先移除,因此将来所有访问该资源请求都应该定向到一个特定的URL上。
Client Error
在 400范围的状态码是客户端错误码。这种类型的错误码往往跟安全相关。
比如,如果一个客户端尝试访问一个未授权访问的资源,服务器就会返回一个状态码 401。类似地,如果客户端尝试访问一个禁止的资源,在这种情况下客户端的认证状态是一样的,那么服务器可能会返回一个状态码403,表示禁止对该资源进 行访问。如 果请求不正确或客户端超时,400级错误码也可能被返回。然而,有一个400级的代码总是具有误导性:404。虽然这个代码在技术上被归类为客户端错误,但是事实上它可以同时表示客户端或服务器上的错误。但这个错误码只是简单地显示为没有找到请求的资源。当这个错误发生在客户端时,它往往表示的是网络连接 问题。在其他时候,这个错误的发生还可能是由于资源已从服务器上转移或重命名而造成的。
Server Error
500 级状态码表示的是服务器错误。
比如,如果Web服务器超时,它就会产生一个504错误。虽然,一个500级的错误往往表示的不是服务器的问题,而是在服务 器上运行的Web应用的问题。比如,我自己的个人网站是用ASP编写的,它负责动态生成HTML网页。在调试的过程中,有Bug的代码总会导致我的Web 服务器返回HTTP状态码500,该代码是一般表示内部服务器错误。这个代码只是出现问题了,并且HTTP无法解决该问题。

41.进程之间通讯binder机制
答:(大致)Binder实现服务端进程与客户端进程之间通信的这么一个架构。
其中包括三部分,服务端,Binder驱动,客户端。
Binder服务器端:就是一个继承于Binder的对象,它里面定义实现了各种方法(服务)
Binder驱动:当服务器端创建一个Binder对象的时候,Binder驱动里会相应的创建一个mRemote对象,和服务端一样,都是Binder对象。
客户端:客户端可以通过获取Binder驱动的mRemote对象的引用,然后就可以调用Binder对象的服务了。
Binder机制下的两个进程之间的通信基本就是上面那样一个过程:即服务端定义服务,客户端通过获取服务端的对象引用的方式(通过中介Binder驱动),然后就可以调用服务端定义的各种服务。
Binder机制实现进程间通信的关键就是获取到服务端的代理,只要获取到服务端的代理,那么就可以调用服务端的方法,实现通信。安卓里面管理这些服务的有一个东西叫做ServiceManager(他本身也是个Service),当我们想要获取某个服务的代理时,就必须通过他,ServiceManager掌握着所有Service的句柄,即你只要找他,他就能给你找到你要的service的句柄,然后有了句柄就可以得到BpBinder(Binder代理)了,也就是可以获取到你想要的服务的代理了
42.Json字符串解析的原理过程
答:1、JSON-java最重要的类有三个。
JSONObject : 包装一个map。 用来表示一个{k:v,k2:v2,k3:[1,2]}形式的json数据
JSONArray :包装一个ArrayList。用来表示一个[1,2,{k:v}]形式的json数据
JSONTokener:包装一个Reader。用来存储、读取、操作一个表示JSON数据的字符串
2、原理
1、JSONObject和JSONArray都可以用一个JSONTokener作为构造参数去实例化。
2、解析时可能会产生多个JSONObject或者JSONArray。但是他们都是操作同一个JSONTokener。
3、JSONObject和JSONArray可以分别通过JSONTokener提供的方法解析出对方。可以实现嵌套。
43.图片加载三级缓存
答:1、内存缓存 优先加载,速度最快
2、本地缓存 次优先加载 速度稍快
3、网络缓存 最后加载 速度由网络速度决定(浪费流量)
44.App启动的流程
答:整个应用程序的启动过程要执行很多步骤,但是整体来看,主要分为以下五个阶段:

一. Step1 - Step 11:
Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity;
二. Step 12 - Step 16:
ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态;
三. Step 17 - Step 24:
Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,
于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,
即将要启动的Activity就是在这个ActivityThread实例中运行;
四. Step 25 - Step 27:
ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,
以便以后ActivityManagerService能够通过这个Binder对象和它进行通信;
五. Step 28 - Step 35:
ActivityManagerService通过Binder进程间通信机制通知ActivityThread,
现在一切准备就绪,它可以真正执行Activity的启动操作了。
45.Apk包含了哪天东西,打包的流程
答:apk包含内容:
1. META-INF\(注:Jar文件中常可以看到)(签名文件夹);
2. res\(注:存放资源文件的目录);
3. AndroidManifest.xml(注:程序全局配置文件);
4. classes.dex(注:Dalvik字节码);
5. resources.arsc(注:编译后的二进制资源文件)。
Apk打包流程:
1.aapt阶段:使用aapt来打包res资源文件
2.aidl阶段:AIDL (Android Interface Definition Language), Android接口定义语言,Android提供的IPC (Inter Process Communication,进程间通信)的一种独特实现。
这个阶段处理.aidl文件,生成对应的Java接口文件
3.Java Compiler阶段
通过Java Compiler编译R.java、Java接口文件、Java源文件,生成.class文件
4.dex阶段
通过dex命令,将.class文件和第三方库中的.class文件处理生成classes.dex。
5.apkbuilder阶段
将classes.dex、resources.arsc、res文件夹(res/raw资源被原装不动地打包进APK之外,其它的资源都会被编译或者处理)、Other Resources(assets文件夹)、AndroidManifest.xml打包成apk文件。
6.Jarsigner阶段:对apk进行签名,可以进行Debug和Release 签名。
7. zipalign阶段
release mode 下使用 aipalign进行align,即对签名后的apk进行对齐处理。
Zipalign是一个android平台上整理APK文件的工具,它对apk中未压缩的数据进行4字节对齐,对齐后就可以使用mmap函数读取文件,可以像读取内存一样对普通文件进行操作。如果没有4字节对齐,就必须显式的读取,这样比较缓慢并且会耗费额外的内存。
46.数据结构中的堆,堆排序
答:最大(最小)堆是一棵每一个节点的键值都不小于(大于)其孩子(如果存在)的键值的树。大顶堆是一棵完全二叉树,同时也是一棵最大树。小顶堆是一棵完全完全二叉树,同时也是一棵最小树。最大(最小)堆是一棵每一个节点的键值都不小于(大于)其孩子(如果存在)的键值的树。大顶堆是一棵完全二叉树,同时也是一棵最大树。小顶堆是一棵完全完全二叉树,同时也是一棵最小树。

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序
堆排序的基本思路:
  a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;一般升序采用大顶堆,降序采用小顶堆
  b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
  c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
47.Reentrantlock
答:synchronized是java内置的关键字,它提供了一种独占的加锁方式。synchronized的获取和释放锁由JVM实现,用户不需要显示的释放锁,非常方便。然而synchronized也有一定的局限性,例如:当线程尝试获取锁的时候,如果获取不到锁会一直阻塞。如果获取锁的线程进入休眠或者阻塞,除非当前线程异常,否则其他线程尝试获取锁必须一直等待。
    JDK1.5之后发布,加入了Doug Lea实现的concurrent包。包内提供了Lock类,用来提供更多扩展的加锁功能。Lock弥补了synchronized的局限,提供了更加细粒度的加锁功能。ReentrantLock是Lock的默认实现之一。弄清楚几个概念
可重入锁。可重入锁是指同一个线程可以多次获取同一把锁。ReentrantLock和synchronized都是可重入锁。
可中断锁。可中断锁是指线程尝试获取锁的过程中,是否可以响应中断。synchronized是不可中断锁,而ReentrantLock则提供了中断功能。
公平锁与非公平锁。公平锁是指多个线程同时尝试获取同一把锁时,获取锁的顺序按照线程达到的顺序,而非公平锁则允许线程“插队”。synchronized是非公平锁,而ReentrantLock的默认实现是非公平锁,但是也可以设置为公平锁。
48.Java中的异常
答:程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?Java提供了更加优秀的解决办法:异常处理机制。
异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。
Throwable类是Java异常类型的顶层父类,一个对象只有是 Throwable 类的(直接或者间接)实例,他才是一个异常对象,才能被异常处理机制识别。Throwable又派生出Error类和Exception类。
错误:Error类以及他的子类的实例,代表了JVM本身的错误。错误不能被程序员通过代码处理,Error很少出现。因此,程序员应该关注Exception为父类的分支下的各种异常类。
异常:Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用,是异常处理的核心。
try{
     try块中放可能发生异常的代码。
     如果执行完try且不发生异常,则接着去执行finally块和finally后面的代码
     如果发生异常,则尝试去匹配catch块。
}catch(SQLException SQLexception){
    每一个catch块用于捕获并处理一个特定的异常,或者这异常类型的子类。Java7中可以将多个异常声明在一个catch中。
    catch后面的括号定义了异常类型和异常参数。如果异常与之匹配且是最先匹配到的,则虚拟机将使用这个catch块来处理异常。
    在catch块中可以使用这个块的异常参数来获取异常的相关信息。异常参数是这个catch块中的局部变量,其它块不能访问。
    如果当前try块中发生的异常在后续的所有catch中都没捕获到,则先去执行finally,然后到这个函数的外部caller中去匹配异常处理器。
    如果try中没有发生异常,则所有的catch块将被忽略。
}catch(Exception exception){
    //...
}finally{
    finally块通常是可选的。
   无论异常是否发生,异常是否匹配被处理,finally都会执行。
   一个try至少要有一个catch块,否则, 至少要有1个finally块。但是finally不是用来处理异常的,finally不会捕获异常。
  finally主要做一些清理工作,如流的关闭,数据库连接的关闭等。 
}
throws声明:如果一个方法内部的代码会抛出检查异常(checked exception),而方法自己又没有完全处理掉,则javac保证你必须在方法的签名上使用throws关键字声明这些可能抛出的异常,否则编译不通过。
throws是另一种处理异常的方式,它不同于try...catch...finally,throws仅仅是将函数中可能出现的异常向调用者声明,而自己则不具体处理。
采取这种异常处理的原因可能是:方法本身不知道如何处理这样的异常,或者说让调用者处理更好,调用者需要为可能发生的异常负责。
public void foo() throws ExceptionType1 , ExceptionType2 ,ExceptionTypeN
{ 
     foo内部可以抛出 ExceptionType1 , ExceptionType2 ,ExceptionTypeN 类的异常,或者他们的子类的异常对象。
}
1. Java.lang.NullPointerException 
  这个异常大家肯定都经常碰到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的对象,这个错误经常出现在创建图片,调用数组这些操作中,比如图片未经初始化,或者图片创建时的路径错误等等。对数组操作中出现空指针,很多情况下是一些刚开始学习编程的朋友常犯的错误,即把数组的初始化和数组元素的初始化混淆起来了。数组的初始化是对数组分配需要的空间,而初始化后的数组,其中的元素并没有实例化,依然是空的,所以还需要对每个元素都进行初始化(假如要调用的话) 
2. java.lang.ClassNotFoundException 
  这个异常是很多原本在JB等开发环境中开发的程序员,把JB下的程序包放在WTk下编译经常出现的问题,异常的解释是"指定的类不存在",这里主要考虑一下类的名称和路径是否正确即可,假如是在JB下做的程序包,一般都是默认加上Package的,所以转到WTK下后要注重把Package的路径加上。 
3. java.lang.ArithmeticException 
  这个异常的解释是"数学运算异常",比如程序中出现了除以零这样的运算就会出这样的异常,对这种异常,大家就要好好检查一下自己程序中涉及到数学运算的地方,公式是不是有不妥了。 
4. java.lang.ArrayIndexOutOfBoundsException 
  这个异常相信很多朋友也经常碰到过,异常的解释是"数组下标越界",现在程序中大多都有对数组的操作,因此在调用数组的时候一定要认真检查,看自己调用的下标是不是超出了数组的范围,一般来说,显示(即直接用常数当下标)调用不太轻易出这样的错,但隐式(即用变量表示下标)调用就经常出错了,还有一种情况,是程序中定义的数组的长度是通过某些特定方法决定的,不是事先声明的,这个时候,最好先查看一下数组的length,以免出现这个异常。 
5. java.lang.IllegalArgumentException 
  这个异常的解释是"方法的参数错误",很多J2ME的类库中的方法在一些情况下都会引发这样的错误,比如音量调节方法中的音量参数假如写成负数就会出现这个异常,再比如g.setColor(int red,int green,int blue)这个方法中的三个值,假如有超过255的也会出现这个异常,因此一旦发现这个异常,我们要做的,就是赶紧去检查一下方法调用中的参数传递是不是出现了错误。 
6. java.lang.IllegalAccessException 
  这个异常的解释是"没有访问权限",当应用程序要调用一个类,但当前的方法即没有对该类的访问权限便会出现这个异常。对程序中用了Package的情况下要注重这个异常。
49.逻辑地址和物理地址,为什么使用逻辑地址
答:逻辑地址(虚拟地址)是操作系统建立,方便程序访问变量;物理地址是绝对地址,实际地址。逻辑地址是为了程序结构化而做的设计,分层设计,直接访问硬件地址的模块,对下是使用物理地址,对上封装成逻辑地址,是为了程序移植方便。举个例子,大学里快递点分发快递会给学生发一个短信里面包含一个快递ID(类似B103),学生通过这个ID到快递点找B103取快递。这里B103就是逻辑地址,而物理地址指实际的货物配送地址。快递点和学生都没有必要通过物理地址找货物,所以新建了逻辑地址。
50.进程之间的通信机制有哪些
答:linux进程间通讯实现方式有很多种。包含管道、信号、共享内存、套接字而 管道、信号、共享内存 这三种方式只适用于同一台设备间进程间通讯。套接字可以跨设备进行进程间通讯。Android系统没有采用上述提到的各种进程间通信机制,而是采用Binder机制 ,android中常见的一些进程间通信 AIDL,BraodCast,ContentProvider
IPC这个名词,他的全名叫做:跨进程通信(interprocess communication), 因为在Android系统中,个个应用程序都运行在自己的进程中,进程之间一般是无法直接进行数据交换的, 而为了实现跨进程,Android给我们提供了上面说的Binder机制,而这个机制使用的接口语言就是: AIDL(Android Interface Definition Language),他的语法很简单,而这种接口语言并非真正的编程 语言,只是定义两个进程间的通信接口而已
51.Arraylist如何删除重复的元素或者指定的元素
答:删除指定的元素可以直接使用remove方法,删除重复元素有两种方式:
使用HashSet来删除重复的元素。如你所知,HashSet不允许有重复的元素。我们使用HashSet的这个属性来删除已建 成的ArrayList中的重复元素。但是,这种方法有一个缺点。那就是,它会删除ArrayList中元素的插入顺序。这意味着,删除重复的元素后,元 素的插入顺序就不对了
使用LinkedHashSet删除ArrayList中重复的元素。正如你知道的,LinkedHashSet不允许重复元素, 同时保持元素的插入顺序。LinkedHashSet的这两个属性可以确保在删除ArrayList中的重复元素之后,依然保持元素的插入顺序
52.Java中 的内部类为什么可以访问外部类 
答:内部类就是定义在一个类内部的类。定义在类内部的类有两种情况:一种是被static关键字修饰的, 叫做静态内部类, 另一种是不被static关键字修饰的, 就是普通内部类。 
静态内部类虽然也定义在外部类的里面, 但是它只是在形式上(写法上)和外部类有关系, 
其实在逻辑上和外部类并没有直接的关系。而一般的内部类,不仅在形式上和外部类有关系(写在外部类的里面), 在逻辑上也和外部类有联系。这种逻辑上的关系可以总结为以下两点:1 内部类对象的创建依赖于外部类对象;2 内部类对象持有指向外部类对象的引用。
上边的第二条可以解释为什么在内部类中可以访问外部类的成员。就是因为内部类对象持有外部类对象的引用。


 

猜你喜欢

转载自blog.csdn.net/u010365819/article/details/79204959