<持续更新中>面试准备

比较好的面试准备系列

Android面试

Android面试一天一题

重写 override 父子类之间
返回类型一样 参数列表一样
更加容易被访问 更小的异常

接口比抽象类更加抽象
抽象类中可以定义构造器,可以有抽象方法和具体方法,
而接口中不能定义构造器而且其中的方法全部都是抽象方法。
抽象类中的成员可以是private、默认、protected、public的,而接口中的成员全都是public的。
抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。
有抽象方法的类必须被声明 为抽象类,而抽象类未必要有抽象方法。
抽象类不能够new 一个对象 抽象类无法实例化,无法创建对象

静态的方法是无法被重写的

里氏代换原则[能使用父类型的地方一定能使用子类型]

事务的ACID是指什么?
答:
- 原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;
- 一致性(Consistent):事务结束后系统状态是一致的;
- 隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
- 持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。

补充:关于事务,在面试中被问到的概率是很高的,可以问的问题也是很多的。首先需要知道的是,只有存在并发数据访问时才需要事务。

线程的sleep()方法和yield()方法有什么区别?
答:
① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
④ sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。

Error类和Exception类的父类都是throwable类,他们的区别是:
Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,
仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。Exception类表示程序可以处理的异常,可以捕获且可能恢复。
遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。Exception类又分为运行时异常
(Runtime Exception)和受检查的异常(Checked Exception ),运行时异常;ArithmaticException,IllegalArgumentException,
编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。而受检查的异常,要么用try。。
。catch捕获,要么用throws字句声明抛出,交给它的父类处理,否则编译不会通过。

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

2)禁止进行指令重排序。

volatile只提供了保证访问该变量时,每次都是从内存中读取最新值,并不会使用寄存器缓存该值——每次都会从内存中读取。

而对该变量的修改,volatile并不提供原子性的保证。

由于及时更新,很可能导致另一线程访问最新变量值,无法跳出循环的情况

多线程下计数器必须使用锁保护。

Ant和Maven都是基于Java的构建(build)工具。理论上来说,有些类似于(Unix)C中的make ,但没有make的缺陷。Ant是软件构建工具,Maven的定位是软件项目管理和理解工具。
Ant特点 ›
没有一个约定的目录结构 ›必须明确让ant做什么,什么时候做,然后编译,打包 ›没有生命周期,必须定义目标及其实现的任务序列 ›没有集成依赖管理
Maven特点
›拥有约定,知道你的代码在哪里,放到哪里去 ›拥有一个生命周期,例如执行 mvn install 就可以自动执行编译,测试,打包等构建过程 ›只需要定义一个pom.xml,然后把源码放到默认的目录,Maven帮你处理其他事情 ›拥有依赖管理,仓库管理

目前的问题:父类的功能无法满足子类的需求。
方法重写的前提: 必须要存在继承的关系。
方法的重写: 子父类出了同名的函数,这个我们就称作为方法的重写。

什么是时候要使用方法的重写:父类的功能无法满足子类的需求时。
方法重写要注意的事项:
    1.方法重写时, 方法名与形参列表必须一致。
    2.方法重写时,子类的权限修饰符必须要大于或者等于父类的权限修饰符。
    3.方法重写时,子类的返回值类型必须要小于或者 等于父类的返回值类型。
    4.方法重写时, 子类抛出的异常类型要小于或者等于父类抛出的异常类型。
            Exception(最坏)
            RuntimeException(小坏)
方法的重载:在一个类中 存在两个或者两个 以上的同名函数,称作为方法重载。
方法重载的要求
    1. 函数名要一致。
    2. 形参列表不一致(形参的个数或形参 的类型不一致)
    3. 与返回值类型无关。

父类的私有成员和构造函数都不能被继承,只能调用。

包含抽象方法的类必须定义为抽象类; 抽象类不一定包含抽象方法,也可以包含普通方法; 抽象类有构造方法,但是不能new一个对象,不能实例化; 抽象类只支持单继承。

在创建子类的对象时,若不含带参构造函数,将先执行父类的无参构造函数,然后再执行自己的无参构造函数。

子类可以在自己的构造函数中使用super关键字来调用父类的含参数构造函数,但这个调用语句必须是子类构造函数的第一个可执行语句

在一个子类被创建的时候,首先会在内存中创建一个父类对象,然后在父类对象外部放上子类独有的属性,两者合起来形成一个子类的对象。所以所谓的继承使子类拥有父类所有的属性和方法其实可以这样理解,子类对象确实拥有父类对象中所有的属性和方法,但是父类对象中的私有属性和方法,子类是无法访问到的,只是拥有,但不能使用。就像有些东西你可能拥有,但是你并不能使用。所以子类对象是绝对大于父类对象的,所谓的子类对象只能继承父类非私有的属性及方法的说法是错误的。可以继承,只是无法访问到而已。

Dalvik和Java运行环境的区别:
1:Dalvik主要是完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等等重要功能。   
2:Dalvik负责进程隔离和线程管理,每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。   
3:不同于Java虚拟机运行java字节码,Dalvik虚拟机运行的是其专有的文件格式Dex   4:dex文件格式可以减少整体文件尺寸,提高I/o操作的类查找速度。   
5:odex是为了在运行过程中进一步提高性能,对dex文件的进一步优化。   
6:所有的Android应用的线程都对应一个Linux线程,虚拟机因而可以更多的依赖操作系统的线程调度和管理机制   
7:有一个特殊的虚拟机进程Zygote,他是虚拟机实例的孵化器。它在系统启动的时候就会产生,它会完成虚拟机的初始化,库的加载,预制类库和初始化的操作。如果系统需要一个新的虚拟机实例,它会迅速复制自身,以最快的数据提供给系统。对于一些只读的系统库,所有虚拟机实例都和Zygote共享一块内存区域。

super关键字是在子类对象内部指代其父类对象的引用

StringBuffer是线程安全,所有跟字符串对象操作有关的操作就加了同步锁
StringBuilder是非线程安全的,但是单线程环境下访问操作就比StringBuffer更高效

Java.Thread的方法resume()负责重新开始被以下哪个方法中断的线程的执行
suspend

关于HashMap与HashTable
两者都是用key-value方式获取数据
HashMap不是同步的,而Hashtable是同步的
迭代HashMap采用快速失败机制,而Hashtable不是

二叉树是非线性数据结构,所以 顺序存储结构和链式存储结构都能存储

堆的形状是一棵完全二叉树

Java中的集合类包括ArrayList、LinkedList、HashMap等类,
ArrayList的访问速度比LinkedList快
HashMap实现Map接口,它允许任何类型的键和值对象,并允许将null用作键或值

ArrayList和LinkedList均实现了List接口


关于ServiceConnection接口的onServiceConnected()方法的触发条件描述正确的是?

bindService是异步调用和Service进行绑定, 如果绑定成功, 则会调用ServiceConnection的onServiceConnected
当调用bindService方法后就会回调Activity的onServiceConnected,在这个方法中会向Activity中传递一个IBinder的实例,Acitity需要保存这个实例

Theme窗体级别,style窗体元素级别。所以Theme作用在activity上
Theme被final修饰,是不可以被继承的

andorid数据持久化的方法。
1.文件IO(直接写入SD卡文件);
2.SQLite数据库;
3.使用Preferences。 Preferences其实也属于文件IO;
4.ContentProvider。作为android4大组件之一,其本身也是为了实现进程间数据共享。可能有的小伙伴会产生
疑惑,说这和持久化有毛的关系(我自己就是这样,因为基础不牢了。。)。数据持久化就是将内存中的数据模型转化
为存储模型。这样就明白了把。反观,ContentProvider,会发现其中好多方法和SQLite数据库操作方法有的一拼,heh
到这里 ,我们就明白了为什么把ContentProvider也是持久化了把。但是 ContentProvider的主要目的还是为了数据共享。

一个GLSurfaceView类 , 具有以下特点 :
1.管理一个平面, 这个平面是一个特殊的内存块 , 它可以和 android 视图系统混合 .
2.管理一个EGL 显示 , 它能够让 OpenGL 渲染到一个平面 .
3.接受一个用户提供的实际显示的Renderer 对象 .
4.使用一个专用线程去渲染从而和UI 线程解耦 .
5.支持on-demand 和连续的渲染.
6.可选的包, 追踪 和 / 或者错误检查这个渲染器的 OpenGL 调用 .

什么是瞬时数据:存储在内存当中,有可能会因为程序的关闭或其他原因导致内存被收回而丢失的数据。
为什么采用数据持久化技术:为了保证关键数据在程序退出时不被丢失。
什么是数据持久化技术:将内存中的瞬时数据保存到存储设备中,保证手机在关机的情况下数据仍然不会丢失。
安卓提供了三种方式用于简单的数据持久化功能:
1. 文件储存;
2. SharedPreference存储;
3. SQLite数据库储存

ContentProvider?
1.1 Android提供的持久化数据中,包括文件存储、SharedPreferences存储以及sql数据库存储都只能在当前应用程序中访问,其他程序无法访问当前程序中的数据。所以出现了内容提供器ContentProvider

1.2 ContentProvider 系Android四大组件之一,主要用于程序间的数据共享,它提供了一套机制,允许一个程序访问另一个程序中的数据同时还能保证数据的安全性,是Android跨程序共享数据的标准方式。

1.3 和sql的实现差别:
1.3.1 ContentProvider 屏蔽了数据存储的细节,内部实现透明化,用户只需关心uri即可(是否匹配);而sql数据库访问用户需要知道数据表的详情
1.3.2 ContentProvider能实现不同app的数据共享;sql 只能是自己程序才能访问
1.3.3 Contentprovider可以增删本地的文件,xml等信息

Content Provider主要用于在不同的应用程序之间(因而是完成IPC的一种)实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。目前,使用ContentProvider是 Android 实现跨程序共享数据的标准方式,因为它提供了统一的数据访问方式

使用ContentProvider 可以将数据共享给其他应用,让除本应用之外的应用也可以访问本应用的数据。它的底层是用SQLite 数据库实现的,所以其对数据做的各种操作都是以Sql实现,只是在上层提供的是URL。

BroadcastReceiver 的注册与注销在OnStart、OnStop中进行;
OnPause和OnResume两个活动会经常发生,比如休眠或Intent传送,因此在这两个函数中的处理应当简洁
Activity 的可见生命周期发生在 onStart调用与 onStop调用之间。在这段时间,用户可以在屏幕上看到 Activity 并与其交互。
我们可以在 onStart中注册一个 BroadcastReceiver以监控影响 UI 的变化,并在用户无法再看到您显示的内容时在 onStop中将其取消注册。

如果有一些数据在Activity跳转时(或者离开时)要保存到数据库,那么你认为是在onPause好还是在onStop执行这个操作好呢?
onPause较容易被触发,所以我们在做BroadcastReceiver注销时放在onStop要好些。onPause时Activity界面仍然是可见的,如弹出一个Dialog时。但在保存数据时,放在onPause去做可以保证数据存储的有效性,
如果放在onStop去做,在某些情况下Activity走完onPause后有可能还没顺利走到onStop就被系统回收了。
但要注意在onPause中要非常迅速地执行完所需操作,不然会影响到下一个Activity的生命周期函数的调用。
只有这个方法是一定会执行,在异常情况下,onStop()方法可能不会执行

ActivityManagerProxy对象是ActivityManagerService在普通应用进程的一个代理对象,应用进程通过ActivityManagerProxy对象调用ActivityManagerService提供的功能。
应用进程并不会直接创建ActivityManagerProxy对象,而是通过调用ActiviyManagerNative类的工具方法getDefault方法得到ActivityManagerProxy对象。

应用进程需要调用ActivityManagerService提供的功能,返过来,ActivityManagerService也需要调用应用进程的回调操作以达到控制和调配应用进程的目的。
因此,ActivityManagerService也有一个Binder对象–ApplicationThreadProxy,它是IApplicationThread的代理对象。
ApplicationThread类实现了IApplicationThread接口,实现了管理应用的操作,ApplicationThread对象运行在应用进程里,
内部包含了大量启动和停止Activity的接口,此外还包含了启动和停止服务的接口。但因为ApplicationThread运行在Binder线程,
这些接口方法大多都通过Handler传给ActivityThread的内部的H来执行。其实,ApplicationThread是ActivityThread的内部类,
H其实是一个Handler,也是ActivityThread的一个内部类,运行在主线程。对于每一个应用程序来说,都有一个ActivityThread来表示一个应用主线程。
ActivityManagerService,ApplicationThread和ActivityThread之间的关系。ActivityManagerService可以说是Activity的启动入口,相当于主国。ApplicationThread相当于外交官,
作为ActivityManagerService与ActivityThread之间的信使,负责将ActivityManagerService下达的指令呈给ActivityThread的H来处理,以及将ActivityThread的调用请求传给ActivityManagerService。
ActivityThread则相当于诸侯国,对自己辖区内(应用进程)的Activity有直接的控制权,承担Activity启动的大部分工作,但Activity的户口(ActivityStack)在ActivityManagerService手里。
因为ActivityManagerService需要统一调控不同应用进程中的Activity。

启动过程概述
1 无论是通过Launcher来启动Activity还是通过父Activity来启动Activity,都需要通过IPC调用ActivityManagerService的startActivity的方法。
2 ActivityManagerService调用ActivityStarter.startActivityMayWait。经过一系列复杂的调用,收集并记录Activity的启动信息,调整ActivityStack(让栈顶的Activity进入pause状态),
创建并初始化Application对象(如果有必要的话),创建ActivityThread并调用main方法(如果有必要的话)。
3 最后在ActivityStackSupervisor的realStartActivityLocked方法调用app.thread.scheduleLaunchActivity方法。也就是说
,ActivityManagerService调用ApplicationThread的scheduleLaunchActivity接口方法。
4 ApplicationThread将这个启动信息通过Handler转发给ActivityThread(H)。
5 ActivityThread通过ClassLoader加载相应的Activity类,调用Activity的onCreate方法。

Activity生命周期的几个过程,我们就来说一说这几个过程
1.启动Activity:系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态。
2.当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause方法,暂停当前Activity的执行。
3.当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。
4.当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。
5.用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。
6.当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。
7.用户退出当前Activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。

横竖屏切换时候activity的生命周期:
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

当前的Activity不销毁:
那么就需要在AndroidManifest.xml配置文件中的Activity标签下面添加:android:configChanges=”orientation|keyboardHidden”
然后在activity中重写onConfigurationChanged()方法,每次旋转时会调用该方法,可以再该方法中处理数据。

销毁当前的Activity:
如果销毁当前的Activity,那么就要重写Activity的两个方法onSaveInstanceState()和 onRestoreInstanceState()
显然从方法名字可以看出一个是保存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值