一、单项选择题 2. 下面的代码运行的结果是______。
class B extends Object
{
static
{
System.out.println("Load B1");
}
public B()
{
System.out.println("CreateB");
}
static
{
System.out.println("Load B2");
}
}
class A extends B
{
static
{
System.out.println("Load A");
}
public A()
{
System.out.println("Create A");
}
}
public class Testclass
{
public static void main(String[] args)
{
new A();
}
}
A.Load B1 Load B2 Create B LoadA Create A B.Load B1 Load B2 Load A Create B Create A C.Load B2 Load B1 Create B Create A Load A D.Create B CreateA Load B1 Load B2 Load A
A B C D
6. 下面代码的运行结果是______。
classA
{
void f()
{
System.out.println("A.f() is called");
}
}
class B extends A
{
void f()
{
System.out.println("B.f() is called");
}
void g()
{
System.out.println("B.g() is called");
}
}
public class Test {
public static void main(String[] args) {
A a=new B();
a.g();
}
}
A.B.g() is called B.编译错误 C.运行时错误
A B C
B
[解析] 因为A中没有方法g()。因此会有编译错误。
9. 输出结果是______。
public class Test
{
public static int testStatic()
{
static final int i=0;
System.out.println(i++);
}
public static void main(String args[])
{
Test test=new Test();
test.testStatic();
}
}
A B C D
D
[解析] 在Java语言中,不能在成员函数内部定义static变量。
15. 下面程序的输出结果是______。
public class Foo {
public static void main(String[] args) {
try {
return;
} finally {
System.out.println("Finally");
}
}
}
A.Finally B.编译失败 C.代码正常运行但没有任何输出 D.运行时抛出异常
A B C D
三、论述题 1. 请描述一下Activity生命周期及其各方法。
一个Activity的完整生命周期是: onCreate()→onStart()→onResume()→onPause()→onStop()→onDestroy()。 ●onCreate():Activity第一次被创建的时候调用,通常在该方法里进行一些初始化操作,例如加载布局、组件和绑定事件等; ●onStart():当Activity创建完后,此时由不可见状态变成可见状态,调用onStart(); ●onResume():处于运行状态(Activity位于工作栈栈顶)时调用,用户可进行触碰点击页面上的各种按钮,从而与活动进行交互; ●onPause():当前Activity去启动其他活动时会调用,例如Activity在运行中,用户点击某个按钮触发了一个对话框形式的活动弹出,此时Activity处于暂停状态,触发onPause(),但Activity并不是完全不可见的; ●onStop():Activity处于完全不可见状态就调用,注意它跟onPause()的区别; ●onDestroy():Activity销毁前调用,调用之后Activity就会被销毁。
[解析] 遇到此类问生命周期的题第一时间是要先想到Activity的一个完整的生命周期是怎样的,然后再具体到每个阶段的方法又是怎样的。
2. 如果一个Activity正在运行,这时从前台切换到后台,然后再回到前台,这一整个过程Activity的生命周期是怎样的?
该Activity从被创建到正在运行,依次调用了onCreate()、onStart()和onResume();然后Activity从前台切换到后台中,该Activity这时调用onPause(),然后等完全切换到了后台画面后,Activity调用onStop();这时再把Activity切换回前台中去,Activity此时依次调用onRestart()、onStart()和onResume()方法。以上就是该题中Activity的生命周期全过程了。
[解析] 这类题就是典型的结合例子来考查面试者对Activity生命周期每个方法的熟悉度了。其实不管例子怎么变,只需把题中的几个关键词给找出来,然后与Activity生命周期各个方法联系起来即可。很明显,该题中几个关键词分别是:“正在运行”“前台切换到后台”和“再回到前台”,相信看到这个几个关键词应该能有一个解题思路了吧。
3. Activity在横竖屏切换的时候生命周期是怎样的?
①当不设置configChanges属性时,Activity在切换横竖屏的时候,会执行各个生命周期的方法,横屏执行一轮,竖屏也执行一轮; ②当为Activity设置android:configChanges="orientation"后,再进行横竖屏切换的时候,Activity不再执行生命周期其他方法,横竖屏各执行一次onConfigurationChanged()方法; ③当为Activity设置android:configChanges="orientation|screenSize"后,跟设置"orientation"的效果一样。 另外,configChanges属性的其他值的作用如下: ●orientation:屏幕在纵向和横向间旋转; ●screenSize:屏幕大小改变了; ●keyboard:键盘类型变更,例如手机从12键盘切换到全键盘; ●keyboardHidden:键盘显示或隐藏; ●fontScale:用户变更了首选的字体大小; ●locale:用户选择了不同的语言设定。
[解析] 像这样的题显然靠理论知识是很难推测出来的,所以面试官也是想考察求职者的实践代码能力是否够强。那么就用代码厘清此题的思路。 这里新建一个活动类BActivity,如下所示: public class BActivity extends AppCompatActivity { private static final String TAG="BActivity"; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_b); Log.d(TAG,"onCreate:"); } @Override protected void onStart() { super.onStart(); Log.d(TAG,"onStart:"); } @Override protected void onResume(){ super.onResume(); Log.d(TAG,"onResume:"); } @Overide protected void onPause() { super.onPause(); Log.d(TAG,"onPause:"); } @Override protected void onStop() { super.onStop(); Log.d(TAG,"onStop:"); } @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG,"onDestroy:"); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); Log.d(TAG,"onConfigurationChanged:"); } } 然后运行,打印它的生命周期方法: 07-26 14:23:52.062 7309-7309/com.example.pingred.javatest D/BActivity: onCreate: 07-26 14:23:52.067 7309-7309/com.example.pingred.javatest D/BActivity: onStart: 07-26 14:23:52.073 7309-7309/com.example.pingred.javatest D/BActivity: onResume: 然后切换横屏: 07-26 14:24:00.206 7309-7309/com.example.pingred.javatest D/BActivity: onPause: 07-26 14:24:00.208 7309-7309/com.example.pingred.javatest D/BActivity: onStop: 07-26 14:24:00.254 7309-7309/com.example.pingred.javatest D/BActivity: onCreate: 07-26 14:24:00.258 7309-7309/com.example.pingred.javatest D/BActivity: onStart: 07-26 14:24:00.259 7309-7309/com.example.pingred.javatest D/BActivity: onResume: 现在再切回竖屏: 07-26 14:24:29.698 7309-7309/com.example.pingred.javatest D/BActivity: onPause: 07-26 14:24:29.701 7309-7309/com.example.pingred.javatest D/BActivity: onStop: 07-26 14:24:29.736 7309-7309/com.example.pingred.javatest D/BActivity: onCreate: 07-26 14:24:29.741 7309-7309/com.example.pingred.javatest D/BActivity: onStart: 07-26 14:24:29.743 7309-7309/com.example.pingred.javatest D/BActivity: onResume: 现在在配置文件AndroidManifest.xml中为BActivity添加:android:configChanges="orientation",然后运行后,切换到横屏: 07-26 14:50:07.719 7311-7311/com.example.pingred.javatest D/BActivity: onCreate: 07-26 14:50:07.723 7311-7311/com.example.pingred.javatest D/BActivity: onStart: 07-26 14:50:07.724 7311-7311/com.example.pingred.javatest D/BActivity: onResume: 07-26 15:18:43.721 7312-7312/com.example.pingred,javatest D/BActivity: onConfigurationChanged: 此时再切回竖屏: 07-26 14:50:07.719 7311-7311/com.example.pingred.javatest D/BActivity: onCreate: 07-26 14:50:07.723 7311-7311/com.example.pingred.javatest D/BActivity: onStart: 07-26 14:50:07.724 7311-7311/com.example.pingred javatest D/BActivity: onResume: 07-26 15:18:43.721 7312-7312/com.example.pingred.javatest D/BActivity: onConfigurationChanged: 07-26 15:18:54.424 7312-7312/com example.pingred.javatest D/BActivity: onConfigurationChanged: 之后又在AndroidManifest.xml上为BActivity添加:android:configChanges="orientation|screenSize",然后重复上面的步骤,打印的结果如下: 07-26 14:50:07.719 7311-7311/com.example.pingred.javatest D/BActivity: onCreate: 07-26 14:50:07.723 7311-7311/com.example.pingred.javatest D/BActivity: onStart: 07-26 14:50:07.724 7311-7311/com.example.pingred.javatest D/BActivity: onResume: 07-26 15:18:43.721 7312-7312/com.example.pingred.javatest D/BActivity: onConfigurationChanged: 07-26 15:18:54.424 7312-7312/com.example.pingred.javatest D/BActivity: onConfigurationChanged:
4. 请描述一下Activity的4种启动模式以及它们的应用场景。
standard:标准模式,Activity默认就是standard模式。它也是常说的在正常情况下的模式,每次启动一个活动时,就会创建一个实例,然后被启动的活动入栈,并处于栈顶的位置。 singleTop:该模式下启动Activity,系统会先检查任务栈栈顶是否有该Activity实例,如果有则直接使用它,如果没有则创建新的实例并且入栈到栈顶。一般会将具有推送信息展示的Activity指定为singleTop,因为往往实际中可能会有很多条推送发送与展示,不可能每发一条推送,其Activity就创建一个新例。 singleTask:如果是在同一个应用中(taskAffinity值一样)启动Activity时,系统先检测任务栈中是否存在该Activity,如果存在则直接使用该活动实例,让它置于栈顶,而它之上的其他活动纷纷出栈。如果不存在该实例,则创建该活动新的实例,置于栈顶。如果不是在同一应用中(taskAffinity值不一样),而是其他应用中来启动该模式下的Activity时,那么系统会创建一个新的任务栈,然后创建该活动新的一个实例,将它置于该新建任务栈栈顶。一般实际开发中会将具有程序入口等启动页面的Activity指定为singleTask,这样就可避免在启动页退出的时候因存在多个实例而重复点击几次才能退出的问题。而指定taskAffinity是在AndroidManifest.xml文件里的activity标签里指定: <activity android:name=".MainActivity" android:taskAffinity="com.example.launch" android:launchMode="singleTask"/> 不指定android:taskAfFinity属性,那么它的值默认就是包名。 singleInstance:该模式下启动Activity时,系统会先创建一个新的任务栈来专门存储与管理该Activity。singleInstance跟singleTask类似,唯一的区别就是在singleInstance模式下的Activity具有全局唯一性,就是一个任务栈只有该Activity,任何应用如果启动该Activity使用的都是这个任务栈中的这个实例。该模式的应用场景多用于与其他应用进行交互的情况,例如:闹铃或者紧急呼叫等。
[解析] 既然问到启动模式,就首先应该在脑海中把4种模式的原理图给想象出来。
standard模式的原理如图1所示。
singleTop模式的原理如图2所示。
图1 standard模式 图2 singleTop模式 singleTask模式的原理如图3所示。
图3 singleTask模式 singleInstance模式的原理如图4所示。
图4 singleInstance模式 只要能把它们对应的概念图给想出来,那就能把这4种模式交代清楚了。
5. onNewIntent()与4种启动模式有着什么样的关系?
可以用代码来分析,BActivity设置为singleTask模式,然后点击按钮启动MainActivity,然后跳转到MainActivity页面,再点击按钮启动BActivity,: … @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Log.d(TAG,"onNewIntent:"); } … 然后看一看打印它们的生命周期是怎样的,先运行BActivity的代码,结果如下: 08-04 00:33:50.979 9162-9162/com.example.pingred.test D/BActivity: onCreate: 08-04 00:33:50.983 9162-9162/com.example.pingred.test D/BActivity: onStart: 08-04 00:33:50.985 9162-9162/com.example.pingred.test D/BActivity: onResume: 然后跳转到MainActivity后: 08-04 00:33:57.464 9162-9162/com.example.pingred.test D/BActivity: onPause: 08-04 00:33:57.510 9162-9162/com.example.pingred.test D/MainActivity: onCreate: 08-04 00:33:57.512 9162-9162/com.example.pingred.test D/MainActivity: onStart: 08-04 00:33:57.512 9162-9162/com.example.pingred.test D/MainActivity: onResume: 08-04 00:33:58.033 9162-9162/com.example.pingred.test D/BActivity: onStop: 可以看到此时BActivity最后调用的是onStop()方法。接着继续点击按钮启动BActivity后: 08-04 00:34:00.413 9162-9162/com.example.pingred.test D/MainActivity: onPause: 08-04 00:34:00.436 9162-9162/com.example.pingred.test D/BActivity: onStart: 08-04 00:34:00.436 9162-9162/com.example.pingred.test D/BActivity: onNewIntent: 08-04 00:34:00.436 9162-9162/com.example.pingred.test D/BActivity: onResume: 08-04 00:34:00.965 9162-9162/com.example.pingred.test D/MainActivity: onStop: 08-04 00:34:00.965 9162-9162/com.example.pingred.test D/MainActivity: onDestroy: 当再次启动BActivity时BActivity就会执行onNewIntent()方法。另外需要注意的是如果调用了onNewIntent()方法,那就需要在onNewIntent()方法中调用setIntent(intent)给Activity设置Intent对象,这样做是为了避免在调用getIntent()获取Intent时,得到的是旧的Intent值。 其他模式也可以这样去分析,这里就不做讲解了,可自行去实践探索。
[解析] standard:在默认模式下,每次启动Activity,创建新的实例,但不会调用onNewIntent()。 singleTop:在该模式下,启动的Activity只要在栈顶,就复用该实例,然后就会触发onNewIntent(),如果任务栈不存在该实例,就会创建新实例,可此时并不会调用onNewIntent()。 singleTask:在该模式下,启动的Activity只要任务栈存在该实例,就复用它,此时触发onNewIntent(),如果任务栈不存在该实例,就会创建新实例,可此时并不会调用onNewIntent()。 singleInstance:在该模式下,启动的Activity只要任务栈存在该实例(该模式下的活动是单独占用一个任务栈),就复用它,此时onNewIntent()触发。 上述情况也可以总结为当Activity被restart或者Activity位于栈顶时被再次start这两种情况就会调用onNewIntent()。所以,无论是哪一种模式,只有Activity是在同一个实例的情况下,intent发生了变化,就会调用onNewIntent(),onNewIntent()的作用是让开发者在里面对旧的intent进行保存,对新的intent进行相应处理。