android 面试题

1、Activity的生命周期
2、android的四大组件有哪些
3、android有哪几种存储方式
4、你对android的认识和一些看法(需求、设计、编程和优化等方面进行阐述)
5、android有哪几种动画,并说一下它们之间的区别。
6、问到了自己做的一些android项目。
7、ActivityGroup和ViewGroup的用法
8、Handler和Looper的关系
9、横屏和竖排时候,Activity的生命周期

10、还有问到了一下关于android的优化问题


1, 谈谈你对Activity的理解?

  对于这种“你对什么什么怎么理解”的面试题,最好的回到方式就是用你自己的理解说出来,通俗中夹杂些专业术语,偶尔再蹦出几个英文。当然如果你很牛X,你可以往深了说,只要别漫无目的的说就行。围绕一条主线。这其中如果你对某一方面比较精通,你就应该往你精通的方向引。面试官可能就会顺着你的思路走了。不过现在有很多面试问Android方面的知识不多,问java方面的比较多。

  通俗的讲,Activity就是一个应用程序的门面,也可以理解成就是WEB程序中一个页面,当然与web程序中的页面不同的是,web中的一个页面可能只是一个纯粹的展示页面不与用户进行任何交互,而几乎所有的Activity都会与用户交互。当然两者在架构上也有本质区别,Activity与用户的交互通过触发UI的不同事件完成的。而Web程序是通过请求,响应来完成交互的。还有在android中颠覆了很多常规想法,比如在一个Activity中可以打开另一个不在同一应用的Activity。这在其他程序是不可想象的。当然这种设计的出发点也是为了节省系统资源。从View层的角度来看,Activity承载了与用户交互的不同控件。从控制层看,也就是内部逻辑,Activity需要保持各个界面的状态,背后会做很多持久化的操作。包括妥善管理生命周期的各个阶段。(把生命周期引出来了,没准就会问你这方面的)。

  下面是文档式的回答:(最好的回答方式两者结合)

  首先Activity是android四大组件之一。它是单独的,作为用户与程序交互的一个载体。几乎所有的Activity都与用户交互。Activity创建了一个窗口,你可以通过setContentView这个方法将需要的UI放置在窗口。任何一个应用程序都可以调用单独的一个Activity。

  其次,Activity的继承关系 Activity→ContextThemeWrapper→ContextWrapper→Context

  最后大部分的Activity的子类都需要实现以下两个接口:

  onCreate(Bundle savedInstanceState)接口是初始化activity的地方. 在这儿通常可以调用setContentView(int)设置在资源文件中定义的UI, 使用findViewById(int) 可以获得UI中定义的窗口.

  onPause()接口是使用者准备离开activity的地方,在这儿,任何的修改都应该被提交(通常用于ContentProvider保存数据).

  所有Activity必须在清单文件里注册一下才能使用。

  2, Activity的生命周期?

  在系统中的Activity被一个Activity栈所管理。当一个新的Activity启动时,将被放置到栈顶,成为运行中的Activity,前一个Activity保留在栈中,不再放到前台,直到新的Activity退出为止。

  Activity有四种本质区别的状态:

  1)在屏幕的前台(Activity栈顶),叫做活动状态或者运行状态(active or running)

  2)如果一个Activity失去焦点,但是依然可见(一个新的非全屏的Activity 或者一个透明的Activity 被放置在栈顶),叫做暂停状态(Paused)。一个暂停状态的Activity依然保持活力(保持所有的状态,成员信息,和窗口管理器保持连接),但是在系统内存极端低下的时候将被杀掉。

  3)如果一个Activity被另外的Activity完全覆盖掉,叫做停止状态(Stopped)。它依然保持所有状态和成员信息,但是它不再可见,所以它的窗口被隐藏,当系统内存需要被用在其他地方的时候,Stopped的Activity将被杀掉。

  4)如果一个Activity是Paused或者Stopped状态,系统可以将该Activity从内存中删除,Android系统采用两种方式进行删除,要么要求该Activity结束,要么直接杀掉它的进程。当该Activity再次显示给用户时,它必须重新开始和重置前面的状态。

  Activity提供了7个生命周期方法:

  onCreate(),onStart(),onResume(),onPause(),onStop(),onDestory(),onRestart()。在这七个生命周期方法中有三个关键的循环。其实官方给的那张图画得很明白,但估计很少人能有耐心去揣摩。那就换种方式展现。看图吧:

  1)以下该图呈现了一个Activity完整的生命周期,从onCreate(Bundle)开始到onDestroy()结束。Activity在onCreate()设置所有的“全局”状态,在 onDestory()释放所有的资源。

  首先我们运行程序,这是打开MainActivity依次调用onCreate->onStart->onResume,这时MainActivity在栈顶,与我们交互的Activity都在栈顶。然后我按下返回键,则会依次调用onPause->onStop->onDestory。这属于一个完整的生命周期。

  



  2)可见的生命周期,从onStart()开始到onStop()结束。说白了就是一个Activity被另一个activity完全覆盖掉,然后又重新回到前台这个一个过程称之为可见生命周期。

  首先我们打开OtherActivity这个窗口。此时MainActivity将被覆盖掉。则会依次调用onPause->onStop。在内存不足的时候,系统也会杀死MainActivity进程。

  然后,按下返回键,MainActivity又回到前台此时会调用 onRestart->onStart->onResume。

  



  3)前台的生命周期,从onResume()开始到onPause()结束。在这段时间里,该Activity处于所有Activity的最前面,和用户进行交互。Activity可以经常性地在resumed和paused状态之间切换。说白了就是一个Activity覆盖到另一个Activity上面,但是并没有完全覆盖掉。

  首先,我们将OtherActivity打开,这是OtherActivity以对话框模式打开,悬浮在MainActivity上面。直接调用的onPause()。

  然后 我们按下返回键,则调用的onResume。对于这种没用完全覆盖的状态只会在onPause与onResume两个方法之间切换。

  



  注:还有一种特殊情况,当屏幕发生改变的时候生命周期是怎样的呢?比如由竖屏调整为横屏。生命周期的方法依次用:onPause->onStop->onDestroy->onCreate->onStart->onResume。这么一个过程。它会销毁掉原先的activity,重新创建。

  3, Acitvity启动模式?

  对于这种题,最后就是自己写个例子,观察一下,才能真正明白。

  Activty启动提供了四种启动模式。launchMode:

  standard:每次启动新的活动窗口(new操作)

  singleTop:如果在栈顶是目标活动,则直接打开.否则开启新的活动窗口(new).

  singleTask和singleInstance基本上相同.差别在于若根活动设置为singleTask时,则由此所开启的活动也在同一任务中,即taskId相同。.而若根活动设置为singleInstance时,由此开启的活动在新的任务中.即栈中只有一个活动,taskid不同。.其余情况相同.

  4, 在onCreate方法中Bundle savedInstanceState 这个参数有什么作用?

  在onCreate方法中有saveInstanceState这个参数,其实这个参数对应两个方法。

  void onSaveInstanceState(Bundle outState);void onRestoreInstanceState(Bundle savedInstanceState)。当某个activity变得“容易”被系统销毁时,说白了就是系统在内存不足或者其他异常情况下把你的Activity销毁时,将调用这个方法。需要注意的是它是系统调用的,并且你的Activity是被动得被销毁。你可以在销毁的时候保存一下数据。然后在onCreate方法中拿出来。那什么情况下能触发这两个方法呢?

  1)、当用户按下HOME键时。

  这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则

  2)、长按HOME键,选择运行其他的程序时。

  3)、按下电源按键(关闭屏幕显示)时。

  4)、从activity A中启动一个新的activity时。

  5)、屏幕方向切换时,例如从竖屏切换到横屏时。

  在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行

  总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。

  至于onRestoreInstanceState方法,需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行

  另外,onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原。

  5, 谈谈你对BroadCastRceiver的理解?

  广播接收者,android四大组件之一,也是唯一一个能动态注册的组件。

  1)广播接收者是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播是源自于系统──比如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态。

  2)应用程序可以拥有任意数量的广播接收者以对所有它感兴趣的通知信息予以响应。所有的接收器均继承自BroadcastReceiver基类。

  3)广播接收者没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。

  6, 广播分几种?他们有什么区别?

  广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播。

  然而有序广播是按照接收者声明的优先级别,被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C 。优先级别声明在 intent-filter 元素的 android:priority 属性中,数越大优先级别越高,取值范围:-1000到1000,优先级别也可以调用IntentFilter对象的setPriority()进行设置 。有序广播的接收者可以终止广播Intent的传播,广播Intent的传播一旦终止,后面的接收者就无法接收到广播。

  另外,有序广播的接收者可以将数据传递给下一个接收者,如:A得到广播后,可以往它的结果对象中存入数据,当广播传给B时,B可以从A的结果对象中得到A存入的数据。

  Context.sendBroadcast()

  发送的是普通广播,所有订阅者都有机会获得并进行处理。

  Context.sendOrderedBroadcast()

  发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,

  前面的接收者有权终止广播(BroadcastReceiver.abortBroadcast()),如果广播被前面的接收者终止,后面的接收者就再也无法获取到广播。对于有序广播,前面的接收者可以将数据通过setResultExtras(Bundle)方法存放进结果对象,然后传给下一个接收者,下一个接收者通过代码:Bundle bundle = getResultExtras(true))可以获取上一个接收者存入在结果对象中的数据。

  7, 广播的生命周期?

  广播的生命周期是非常短的,当发送之后intent会到AndroidManifest.xml文件中找是不是有匹配的action,如果有就会调用Receiver ,然后获得Receiver 对象,再执行onReceive方法,这时候Receiver对象就没有用了,当我们再次点击按钮的时候就会重新获得对象,这就是BroadcastReceiver的生命周期.

  在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(Application No

  Response)的对话框.

  如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成.这里不能使用子线程来解决,因为BroadcastReceiver的生命周期很短,子线程可能还没有结束,BroadcastReceiver就先结束了.BroadcastReceiver一旦结束,此时BroadcastReceiver的所在进程很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程).如果它的宿主进程被杀死,那么正在工作的子线程也会被杀死.所以采用子线程来解决是不可靠的.

  8, 两种注册BroadcastReceiver的方法?

  使用在manifest中注册的方法注册BroadcastReceiver,即使你的应用程序没有启动,或者已经被关闭,这个BroadcastReceiver依然会继续运行,这样的运行机制可能会给软件的用户造成困扰。所以作为程序的开发者,我们希望能够有一种灵活的机制完成BroadcastReceiver的绑定和解除绑定操作。Android当然也考虑到了这些问题,所以在Context这个类当中提供了如下两个函数可以在代码中注册:

  i. registerReceiver(receiver,filter);

  这个函数的作用就是将一个BroadcastReceiver注册到应用程序当中,这个函数接收两个参数,第一个参数是需要注册的BroadcastReceiver对象,第二个是一个IntentFilter。第一个参数是非常容易理解的,第二个参数的作用是定义了哪些Intent才能触发这个注册的BroadcastReceiver对象。

  ii. unregisterReceiver(receiver);

  这个方法就非常的简单了,用于解除BroadcastReceiver的绑定状态。一旦解除完成,响应的BroadcastReceiver就不会再接收系统所广播的Intent了。

  两种注册BroadcastReceiver的方法

  1.在应用程序的代码中进行注册

  注册BroadcastReceiver

  registerReceiver(receiver,filter);

  取消注册BroadcastReceiver

  unregisterReceiver(receiver);

  2.在AndroidManifest.xml当中进行注册

  两种注册BroadcastReceiver方法的比较:

  现在我们了解了两种注册BroadcastReceiver的方法之后,需要考虑一下这两种方法适用的场合:

  i. 第一种注册的方法可以保证在应用程序安装之后,BroadcastReceiver始终处于活动状态,通常用于监听系统状态的改变,比如说手机的电量,wifi网卡的状态(当然,监视这些东西也是取决于软件的需求)。对于这样的BroadcastReceiver,通常是在产生某个特定的系统事件之后,进行相应的操作,比如说wifi网卡打开时,给用户一个提示;

  ii. 第二种注册方法相对第一种要灵活的多,这样注册的BroadcastReceiver通常用于更新UI的状态。一般来说,都是在一个Activity启动的时候使用这样的方法注册BroadcastReceiver,一旦接收到广播的事件,就可以在onReceive方法当中更新当前的这个Activity当中的控件。但是需要注意的是如果这个Activity不可见了,就应该调用unregisterReceiver方法来解除注册

  9, 粘性广播有什么作用?怎么使用?

  粘性广播主要为了解决,在发送完广播之后,动态注册的接收者,也能够收到广播。举个例子首先发送一广播,我的接收者是通过程序中的某个按钮动态注册的。如果不是粘性广播,我注册完接收者肯定无法收到广播了。这是通过发送粘性广播就能够在我动态注册接收者后也能收到广播。

  用法:

  //发送粘性广播

  Public void sendStickyBroadCast(){

  Intent intent=new Intent();

  intent.setAction(“com.iteye.myreceiver.action”);

  intent.putExtra(“name”,”tom”);

  this.sendStickyBroadCast(intent);

  }

  发送粘性广播还需要发送粘性广播的权限:

  //动态注册广播接收者

  MyReceiver mr = new MyReceiver ();

  IntentFilter filter = new IntentFilter();

  filter.addAction("com.iteye.myreceiver.action ");

  filter.addCategory(Intent.CATEGORY_DEFAULT);

  Intent ii = this.registerReceiver(mr, filter);

  String n = ii.getStringExtra("name");

  Toast.makeText(this, "动态注册接收者完成,收到粘性广播,name=" + n, 1).show();

  10,如何控制接收者或者发送方得权限?

  1)如果广播发送方要求接收方必须有某个权限才能收到广播怎么做呢?

  /**

  * 发送广播,指定接收者权限

  * sendBroadcast(i, "com.iteye.permission.receiver");//指定接收者权限

  */

  public void sendBroadcast() {

  //隐式意图,发送广播

  Intent i = new Intent();

  i.setAction("com.iteye.receiver.action");

  i.putExtra("name", "tom");

  this.sendBroadcast(i, " com.iteye.permission.receiver ");

  Log.i("Other",".send ok!");

  }

  在清单文件里receiver必须有这个权限才能收到广播。

  首先,需要定义权限:

  然后,声明权限:

  这时接收者就能收到发送的广播。

  2)反过来,如果接收者要求发送方必须拥有某个权限,我才接收你的广播怎么办呢?

  即使过滤器匹配,如果发送方没有相应权限,接收者也不会接收其广播。


11, 谈谈对service的理解?
  Service,服务。幕后工作者,甘心做绿叶。默默为前台提供支持。Android的核心三组件可以通过电视台进行比喻,电视播放画面可以看作Activity,用户可以通过遥控器切换不同的电视台可以看做是不同Activity之间的切换。电视播放的新闻可以看做是广播发送方,每个观众都是接收者。而电视幕后工作者可以看做是Service,从不抛头露面。默默为Activity提供所需要的内容。
  说到Service,我们最熟悉莫过于windows中的服务。他们都是在后台长时间运行,接受上层指令,完成相关操作。但android中的 service与其他的服务还是有所差别的,service与其他三个组件一样,其进程模型都是可以通过XML进行配置的。调用方和发布方都可以有权利来选择是把这个组件运行在同一个进程下,还是不同的进程下。如果一个Service,是有期望运行在于调用方不同进程的时候,就需要利用Android提供的RPC(Remote Procedure Call Protocol)机制,为其部署一套进程间通信的策略。当然这些策略android已经为你封装好了。你需要了解底层。直接拿来使用即可。RPC其实就是代理模式的一种实现,在调用端和服务端都去生成一个代理类,做一些序列化和反序列化的事情,使得调用端和服务器端都可以像调用一个本地接口一样使用 RPC接口。
  Android中用来做数据序列化的类是Parcel,封装了序列化的细节,向外提供了足够对象化的访问接口
  AIDL (Android Interface Definition Language) ,一种接口定义的语言,服务的RPC接口,可以用AIDL来描述, ADT帮助你自动生成一整套的代理模式需要用到的类,不要要你自己写。下面会给个例子。
  12, service的生命周期?
  在有生命周期的这几个组件中,Service的生命周期最长,其次是Activity最后Receiver。
  Service的生命周期相对Activity简单一些。Service提供了两种启动service的方式,每一种方式对应一套生命周期方法。以下是android提供的图片:
  
  1) 以startService()方式启动的服务,它的生命周期如下:
  onCreate()->onStartCommand() 这时服务已经开启,如果再点击一下启动则只会调用onStartCommand()。这说明service是单例的,只实例化一次。点击停止按钮调用 onDestroy()。销毁。生命周期完成。以下为图示:
  
  2) 以bindService()方式启动服务。调用方式如下:
  onCreate()->onBind() 此时服务绑定。再次绑定则无响应。解除绑定:onUnbind()->onDestroy()。生命周期完成。如图所示:
  
  13, 启动service的两种方法?有什么区别?
  一种是startService(), 另一种是bindService()。这两者的区别是第一种方式调用者开启了服务,即会与服务失去联系,两者没有关联。即使访问者退出了,服务仍在运行。如需解除服务必须显式的调用stopService方法。主要用于调用者与服务没有交互的情况下,也就是调用者不需要获取服务里的业务方法。比如电话录音。而后者调用者与服务绑定在一起的。当调用者退出的时候,服务也随之退出。用于需要与服务交互。
  14, 实现进程内与进程间通信是怎么实现的?
  在linux中进程通信机制有很多种,比如:消息队列(message queue),socket,共享内存(share mermory)等等。但是在Android中,无论是进程内还是进程间,所采用的通信机制,主要是以Binder为核心。Android之所以选择是 Binder作为进程的通信机制,主要是Binder与其他通信方式相比更加快速和简洁,所消耗的内存也是相对较少。当然也有其他方面的原因,比如传统进程通信有可能会增加进程开销,也有安全方面的风险。Binder能解决这些问题。故成为首选的通信方式。
  1) 进程内的通信,与进程间的通信相比,相对容易些。进程内通信肯定要采用绑定的方式开启服务。这样才能与服务进行交互。绑定服务的方法:
  bindService(Intent service, ServiceConnection conn, int flags)
  这个方法的第一个参数很好理解。用于激活哪个服务,第二个参数是关键,服务的连接,这是一个接口,用于接收服务开启或者关闭时返回的数据。实现这个接口要重写两个方法:
  onServiceConnected(ComponentName name, IBinder service):一旦客户端与服务端绑定成功,将有这个方法的第二个参数接收服务端返回的IBinder对象。得到服务端的引用就可以在客户端调用服务里的一些业务方法。这也是进程内通信的主要部分。
  onServiceDisconnected(ComponentName name):这个方法在服务断开是调用,服务被销毁或者被干掉时调用。附件处有例子。
  2) 进程之间的通信,其主要的核心机制同样是Binder。其实Binder底层就是通过Parcel(邮包)来完成数据传输的。进程内通信可以通过IBinder对象来实现业务共享的,但是进程间的通信这种方式就肯定不行了。这时就用到了AIDL。
  AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC).AIDL的IPC机制和EJB所采用的CORBA很类似,进程之间的通信信息,首先会被转换成AIDL协议消息,然后发送给对方,对方收到AIDL协议消息后再转换成相应的对象.由于进程之间的通信信息需要双向转换,所以android采用代理类在背后实现了信息的双向转换,代理类由android编译器生成,对开发人员来说是透明的.
  使用方式如下:
  定义AIDL. //XXXService.aidl,注意扩展名
  package com.iteye.androidtoast;
  interface XXXService {
  void sayHello(in/out/inout String name);//in|out|inout是参数的方向
  }
  ide会自动在gen包下生成对应的 java类,接口文件中生成一个Stub的抽象类,里面包括aidl定义的方法,还包括一些其它辅助方法.值得关注的是 asInterface(IBinder iBinder),它返回接口类型的实例,对于远程服务调用,远程服务返回给客户端的对象为代理对象,客户端 onServiceConnected(ComponentName name, IBinder service)方法引用该对象时不能直接强转成接口类型的实例,而应该使用asInterface(IBinder iBinder)进行类型转换.
  AIDL定义注意事项:
  (1)接口名和aidl文件名相同.
  (2)接口和方法前不用加访问权限修饰符public,private,protected等,也不能用final,static.
  (3)AIDL默认支持的类型包话java基本类型(int,long,boolean等)和(String,List,Map,
  CharSequence),使用这些类型时不需要import声明.对于List和Map中的元素类型必须是AIDL支持的类型.如果使用自定义类型作为参数或返回值,自定义类型必须实现Parcelable接口.
  (4)自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中.
  (5)在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数.
  (6)Java原始类型默认的标记为in,不能为其它标记.
  具体步骤:
  1.创建服务器android项目(server)
  2.创建服务类.CustomerService
  /**
  * 服务类
  */
  public class CustomerService extends Service {
  ...
  }
  3.配置清单注册服务类
  
  
  4.定义aidl文件.
  ICustomerService.aidl
  package com.iteye.androidtoast.aidl;
  interface ICustomerService {
  String sayHello(String name);
  }
  5.ide在gen目录下自动生成java接口.
  6.需要实现CustomerService.onBind()方法的返回值.
  public IBinder onBind(Intent intent) {
  return new ICustomerService.Stub() {
  public String sayHello(String name) throws RemoteException {
  return "hello " + name;
  }
  };
  }
  7.创建客户端项目(android项目)
  8.复制服务端项目aidl文件到客户端(连同包结构一同复制),同样在客户端项目中
  也会生成对应的接口类.同步骤(5).
  9.绑定服务.
  class CustomerConnection implements ServiceConnection{
  public void onServiceConnected(ComponentName name, IBinder service) {
  is = ICustomerService.Stub.asInterface(service);
  }
  public void onServiceDisconnected(ComponentName name) {
  }
  }
  10.绑定服务
  Intent i = new Intent();
  i.setAction(“”)
  this.bindService(i, conn, BIND_AUTO_CREATE);
  11,调用远程服务方法
47、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
不能,一个对象的一个synchronized方法只能由一个线程访问。
48、编程题写一个Singleton出来。
Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。
一般Singleton模式通常有几种种形式:
第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。
public class Singleton {
private Singleton(){}
      //在自己内部定义自己一个实例,是不是很奇怪?
      //注意这是private 只供内部调用
      private static Singleton instance = new Singleton();
      //这里提供了一个供外部访问本class的静态方法,可以直接访问  
      public static Singleton getInstance() {
        return instance;   
      }
    }
    第二种形式:
public class Singleton {
  private static Singleton instance = null;
  public static synchronized Singleton getInstance() {
  //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次     
  //使用时生成实例,提高了效率!
  if (instance==null)
    instance=new Singleton();
return instance;   }
}
其他形式:
定义一个类,它的构造函数为private的,所有方法为static的。
一般认为第一种形式要更加安全些
49Java的接口和C++的虚类的相同和不同处。
由于Java不支持多继承,而有可能某个类或对象要使用分别在几个类或对象里面的方法或属性,现有的单继承机制就不能满足要求。与继承相比,接口有更高的灵活性,因为接口中没有任何实现代码。当一个类实现了接口以后,该类要实现接口里面所有的方法和属性,并且接口里面的属性在默认状态下面都是public static,所有方法默认情况下是public.一个类可以实现多个接口。
50Java中的异常处理机制的简单原理和应用。
当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就是JAVA允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常。所有的异常都是java.lang.Thowable的子类。
51、垃圾回收的优点和原理。并考虑2种回收机制。
Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值