您的位置:首页 > 职场人生

面试题

2015-12-01 17:31 525 查看
#Java#

StringBuffer和StringBuilder:

1. 二者方法基本相同;

2. StringBuffer线程安全,StringBuilder更快;

Vector和ArrayList:

1. ArrayList在内存不够时默认是扩展50% + 1个,Vector是默认扩展1倍。

2. Vector提供indexOf(obj, start)接口,ArrayList没有。

3. Vector线程安全,但是大多数情况下不使用Vector,因为线程安全需要更大的系统开销。

HashTable和HashMap:

1. HashTable有序,HashMap无序;

2. HashTable线程安全;

3. HashTable不支持KV为NULL,HashMap支持KV为NULL;

4. HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。

5. 哈希值的使用不同,HashTable直接使用对象的hashCode,而HashMap重新计算hash值,而且用与代替求模;

Thread和Runnable区别:

1. Runnable可多继承、重复启动;

2. Thread是其子类,会开启新线程;

各种引用:

1. 强引用:不会被GC回收;

2. WeakReference:置为null(不存在强引用)即可被GC回收,常用于存储元数据;

3. SoftReference:置为null也不会被立即回收(除非系统内存不够),常用作缓存;

4. PhantomReference:其get方法永远返回null,常用于跟踪引用对象何时被加入ReferenceQueue。

线程Sleep和wait区别:

1. 来自不同的类,分别是Thread和Object;

2. sleep没有释放锁,而wait释放了锁,使得其他线程可以使用同步控制块或者方法;

3. wait、notify和notifyAll只能在同步控制方法(块)使用,sleep可在任何地方;

4. sleep必须捕获异常,而wait、notify和notifyAll不需要捕获异常;

线程同步(volatile+synchronized+wait()+notify()+notifyAll()):

1. volatile修饰变量,不会造成阻塞,适用于读操作比写操作频繁得多的情况;

2. 普通synchronized方法的锁是所在类的实例,只有当类为单例时才能保证绝对同步;

3. static synchronized方法的锁是类,绝对同步;

4. synchronized(lock)块的锁是lock对象,如果是synchronized(this),则只有当类为单例时才能保证绝对同步;

5. notify()唤醒阻塞队列中的第一个对象,notifyAll()唤醒所有;

volatile vs synchronized:
http://www.javaperformancetuning.com/news/qotm051.shtml
多线程下载文件及断点续传(HttpURLConnection+RandomAccessFile):

1. 初始化文件及其长度:

int fileSize = HttpURLConnection.getContentLength();

RandomAccessFile file = new RandomAccessFile(fileName, "rw”);

file.setLength(filesize);

2. 根据文件长度和线程数目确定每个线程下载的起始位置:

HttpURLConnection.setRequestProperty("Range", “bytes=startPosition-endPosition”);

3. 记录所有Thread的已下载长度,便于下次继续下载,并实时更新;

4. 从指定位置写入:

file.seek(startPosition);

#Android基础#

App、Process、Task、Activity关系:

1. 一般一个APP(即一个包名)对应一个Process(一个虚拟机),某些Process是App的容器,也可能多个App共享一个Process;

2. Task是一个Activity的栈,可能来源于多个App;

3. 四大组件和Application都可在Manifest中指定process包名和mutiprocess属性;

4. 如果A应用调用了B应用的组件,则会启动B的进程,但仍然只有一个Task,因为默认处于同一个stack;

5.一个应用的组件可以被多个不同应用调用,所以可以跑在多个进程中;

6.通过shareuserID可以将多个apk,跑在同一个进程中。
http://blog.csdn.net/guolin_blog/article/details/41087993
Activity/Service生命周期:

1. Service不需要onResume()/onPause()/onStop();

2. startService(): 如果为创建则调用onCreate(),否则onStart(),除非调用stopService()否则一直运行;

3. bindService(): 如果未创建则调用onCreate(),否则onBind(),并返回Ibinder接口,常用于通信;

Service与Activity通信:

1. Activity调用bindService,并实现ServiceConnection接口;

2. Service实现IBinder内部类,调用serviceBinder的transact方法传递数据;

如何启动其他应用:

Intent intent = new Intent(Intent.ACTION_MAIN);

intent.addCategory(Intent.CATEGORY_LAUNCHER);

intent.setComponent(new ComponentName(packageName, className));

而这个className可以通过PackageManager查询Intent得到;

Activity的LaunchMode:

1. standard: 不复用,始终创建新实例放到栈顶;

2. singleTop: 只复用位于栈顶的Activity;

3. singleTask: 复用同一栈中的Activity,将其顶部的所有Activity出栈,并将其置于栈顶;

4. singleInstance: 始终复用,而且是放到另外一个单独的栈中,因此不会使其他Activity出栈;

5. 如果Activity声明为singleInstance,则重复start会调用onNewIntent(),而不是onCreate();

自定义组件:

1. onMeasure() ;确定宽高(UNSPECIFIED,EXACTLY,AT_MOST);

2. onLayout();确定位置(mLeft,mTop,mLeft,mBottom);

3. onDraw() ;只重绘添加了DRAWN标志位的View;
http://blog.csdn.net/qinjuning/article/details/8051811 http://blog.csdn.net/qinjuning/article/details/8074262 http://blog.csdn.net/qinjuning/article/details/7110211
View与SurfaceView:

1. View的显示绘制与事件处理处于同一线程,所以只能在主线程操作UI;

2. SurfaceView中通过SurfaceHolder得到Canvas对象后可以在新线程中绘制,适合快速实时渲染:

SurfaceHolder holder=this.getHolder();

holder.addCallback(new SurfaceHolder.Callback(){

@Override

public void surfaceCreated(SurfaceHolder holder) {

new Thread(){

@Override

public void run(){

Canvas canvas=holder.lockCanvas();// 也可以只重绘某个区域:lockCanvas(Rect)

// Draw something on canvas

holder.unlockCanvasAndPost(canvas);

}

}.start();

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {}

});

3. SurfaceHolder的setType函数来设置绘制的类型:

SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface;

SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface;

SURFACE_TYPE_GPU:适用于GPU加速的Surface;

SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,

在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。

如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了。

SparseArray:

1. 用于替换HashMap<Integer,Object>;

2. 内部采用非递归实现二分查找,而且不会像HashMap一样产生对键值对的封装数据结构,基本上是以时间换空间(put和get慢,但是节省存储开销);

3. 内部还有个DELETE字段,便于remove后下次再重新put;

文件:

1. 读取IOStream:

context.openFileInput(name)

context.openFileOutput(name, mode)

2. 四种mode: MODE_APPEND、MODE_PRIVATE、MODE_WORLD_READABLE、MODE_WORLD_WRITABLE;

SharedPreferences:

1. 读取数据:

SharedPreferences sharedPreferences = activity.getPreferences(mode);

SharedPreferences sharedPreferences = context.getSharedPreferences("config", mode);

2. 四种mode: MODE_MULTI_PROCESS、MODE_PRIVATE、MODE_WORLD_READABLE、MODE_WORLD_WRITABLE;

3.修改数据:

Editor editor = sharedPreferences.edit();

editor.putString("key", "value");

editor.commit();

4. 监听数据:

sharedPreferences.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener(){

@Override

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {}

});

5. 读取其他应用数据:

Context otherAppContext = context.createPackageContext(otherAppPackageName, Context.CONTEXT_IGNORE_SECURITY);

SharedPreferences sharedPreferences = otherAppContext.getSharedPreferences("config", Context.MODE_WORLD_READABLE);

然后还需要在配置文件中声明android:sharedUserId;

ContentProvider:

public static final Uri URI = Uri.parse("content://com.xxx.provider/peoples");

private static final int ITEM = 1, ITEM_ID = 2;

private static final UriMatcher mather = new UriMatcher(UriMatcher.NO_MATCH);

static{

mather.addURI(URI.getAuthority(), "peoples", ITEM);

mather.addURI(URI.getAuthority(), "peoples/#", ITEM_ID);

}

@Override

public String getType(Uri uri){

switch (mather.match(uri)){

case ITEM:

return "vnd.android.cursor.dir/peoplelist";

case ITEM_ID:

return "vnd.android.cursor.item/peopleitem";

default:

throw new IllegalArgumentException("uri Illegal" + uri);

}

}

ContentProvider权限控制:

1. 在Manifest中控制读写权限:android:readPermission(读)、android:writePermission(写)、android:permission(读写);

2. 控制URI路径权限:

<path-permission android:pathPrefix="/hello" android:readPermission="READ_HELLO_CONTENTPROVIDER" />

3. 通过Intent传递URI权限:

Intent intent = new Intent(this,ReadProvider.class);

intent.setClassName("com.example.propermissiongrant", "com.example.propermissiongrant.MainActivity");

intent.setData(Uri.parse("content://cn.wei.flowingflying.propermission.PrivProvider/world/1"));

intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

startActivity(intent);
http://blog.csdn.net/flowingflying/article/details/17412609
SQLite:

1. 数据库结构变动:

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

if (oldVersion < ver) {

db.execSQL("ALTER TABLE table ADD COLUMN column INTEGER");

}

}

2. 事务处理:

db.beginTransaction();

db.beginTransactionWithListener(new SQLiteTransactionListener(){

@Override

public void onBegin() {}

@Override

public void onCommit() {}

@Override

public void onRollback() {}

});

int res=db.update(table, values, whereClause, whereArgs);

if(res>-1){

db.setTransactionSuccessful(); //如果不设置,后面将会滚

}

db.endTransaction();

AsyncTask

1. 内部采用ThreadPoolExecutor+LinkedBlockingQueue+Handler实现;

2. execute方法只能在UI线程执行,且只能执行一次。

Handler+Looper+Message+MessageQueue

1. Handler的obtainMessage方法效率更高。

2. Message内部有个消息池,最大值50,采用链表存储。

3. MessageQueue内部init/destroy/poll/wake等均为native实现。

4. Thread默认是没有相关联的Looper的,可通过prepare()和loop()创建。

5. 一个Handler只关联一个Thread及其MessageQueue。

Serializable与Parcelable:

1. Serializable源于JDK,是为了方便文件操作、数据库、网络流对象序列化;

2. Parcelable源于Android SDK,是为了在组件中传递数据,序列化效率较高、内存开销小,但不适合数据持久化存储;

3. Serializable一般不需要自己写实现,不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObject、readObject方法以实现序列化过程自定义;

4. Parcelable需要实现writeToParcel、describeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义,而序列化的这些操作完全由底层实现。

CursorAdapter:

1. 继承自BaseAdapter,实现了getView(),但是添加了newView()和bindView()抽象方法,其中前者只回调一次,后者会多次回调;

2. Cursor必须包含列_id;

HttpClient(Apache)和UrlConnection(JDK):

1. HttpClient支持所有method和header;

2. HttpClient支持持久连接和自动重定向;

3. HttpClient仅支持HTTP的协议;
http://www.cnblogs.com/devinzhang/archive/2012/01/17/2325092.html
进程间通信:

1. 通过Intent调用;

2. 通过ContentProvider提供通用接口;

3. 通过Broadcast通知;

4. 通过AIDL暴露接口;

线程间通信:

1. Message: 消息,包含ID和数据;

2. Handler: 负责发送和处理Message(比如更新UI);

3. Looper: 负责抽取Message,主线程有默认的Looper,子线程需要调用Looper.prepare和Looper.loop();

4. MessageQueue: 负责以队列方式(FIFO)管理Message;

5. Thread: 负责调度整个消息循环,几消息循环的执行场所;

6. 一个Thread对应一个Looper和一个MessageQueue,但可对应多个Handler;

7. 不确定当前线程时,尽量调用view.post(Runnable), 还可以调用Activity的runOnUiThread(Runnable);

Touch事件传递,多个容器组件事件冲突问题:

1. dispatchTouchEvent(MotionEvent ev) 分发

2. onInterceptTouchEvent(MotionEvent ev) 拦截

3. onTouchEvent(MotionEvent ev) 处理
http://www.cnblogs.com/sunzn/archive/2013/05/10/3064129.html
硬件加速:

1. 3.0以上开始支持;

2. 分application/activity/window/view四个级别;

3. 自定义View时有些方法不支持硬件加速或者开启后效果有差异;
http://blog.csdn.net/song_shi_chao/article/details/7453778 http://blog.csdn.net/gemmem/article/details/7715837
单元测试:
http://www.cnblogs.com/jackxlee/archive/2011/10/21/2220315.html
#Android新API#

Loader/AsyncTaskLoader/CursorLoader(3.0新特性):

1. 实现LoaderManager.LoaderCallBack中的回调方法即可;

2. AsyncTaskLoader继承AsyncTask实现异步任务;

3. 内部通过ContentObserver实现数据变动监听并通知回调;

4. 内部通过在activity的onStart()方法中判断loader状态,防止重复启动;

#Android实际问题#

捕获全局异常:

UncaughtExceptionHandler,重写uncaughtException(Thread thread, final Throwable ex);

监听短信收发:

1. BroadcastReceiver:简单,但只能监听收到短信;

2. ContentOberver:监听短信数据库,不过4.4开始出于安全考虑只有系统短信APP才有这个权限;
http://www.blogjava.net/anymobile/articles/328396.html
布局优化:

1.使用LinearLayout时结合layout:weight,尽量不要写死;单要结合RelativeLayout使用,因为前者用多了会大大增加布局层数,影响布局效率;

2.AdapterView里面使用ViewHolder重用布局,但如果不是每个ITEM布局都相同,最好使用多个布局,而不是通过setVisibility实现,否则会影响性能(虽然不用measure但是会占用内存,而且findViewById也会调用耗时)。

内存优化:

1. 不要在Activity内滥用static变量;

2. 不要在主线程做耗时操作(网络请求、文件和数据库操作等),也不要在子线程更新UI,可以使用Handler或者AsyncTask;

3. decode图片的时候,结合BitmapFactory.Options,先将inJustDecodeBounds设为true,decode之后通过outWidth和outHeight计算inSampleSize,然后将inJustDecodeBounds设为false,并再次decode。

4. Bitmap注意回收: if(bitmap!=null&&!bitmap.isRecycled()){bitmap.recycle();}

5. 执行跨Activity的后台异步任务时,context尽量传applicationContext,而不是activity,否则会因为被引用而造成Activity内的对象在任务执行完之前都不能被释放;

轮询的实现:

1. Service+Thread: 休眠后线程容易挂起或被用户杀掉;

2. Service+AlarmManager+Thread: 调用AlarmManager的setRepeating()开始轮询,调用cancel()方法停止轮询;
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0401/1609.html
其他问题:

1. 多重嵌套Fragment如何有效的同步更新UI?

可在需要同步更新的所有Fragment的onResume()方法注册相同的BroadcastReceiver,然后在onPause()取消注册;当需要同步更新UI时发送广播,这样还能防止去更新已被回收的Fragment而引发的异常。

#软件工程与架构设计#

设计模式:

1. 创建范例(如何创建实例):工厂、单例、建造者等;

2. 结构范例(类和对象复合关系):适配器、代理、组合、桥接等;

3. 行为范例(对象之间如何通讯):观察者、命令、迭代器等;

架构设计:

1. 如何设计网络请求与响应框架;

2. 如何设计图片加载和缓存框架;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: