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

最近收集的一些面试题

2016-09-19 16:29 337 查看
最近遇到一些比较有代表性,有点挑战性的面试题,

大概集中这4个方面:

1.性能的优化

2.功能的实现原理

3.基础知识的掌握程度

4.新技术的了解

关于这些问题,觉得下面几篇无论是文章的逻辑,文章的深度都是写得比较好的,希望对一些应聘者有所帮助.

1. JNI 的调用怎么做优化?

思路:

在 Java 中声明一个 native 方法,然后生成本地接口的函数原型声明,再用 C/C++ 实现这些函数,并生成对应平台的动态共享库放到 Java 程序的类路径下,最后在 Java 程序中调用声明的 native 方法就间接的调用到了 C/C++ 编写的函数了,在 C/C++ 中写的程序可以避开 JVM 的内存开销过大的限制、处理高性能的计算、调用系统服务等功能.

遇到的问题:

其实在JNI中,与java最常接触的无非就是查找 class 和 ID (属性和方法 ID),但是这个查找的过程是十分消耗时间的.

解决方法:

因此在 native 里保存 class 和 member id 是很有必要的,但是class 和 member id 在一定范围内是稳定的,但在动态加载的 class loader 下,保存全局的 class 要么可能失效,要么可能造成无法卸载classloader,在诸如 OSGI(j2e的东西,自己百度) 框架下的 JNI 应用还要特别注意这方面的问题.

总结:

所以在 JNI 开发中,合理的使用缓存技术能给程序提高极大的性能。缓存有两种,分别为使用时缓存和类静态初始化时缓存,区别主要在于缓存发生的时刻。

使用时缓存:

字段 ID、方法 ID 和 Class 引用在函数当中使用的同时就缓存起来.

判断字段 ID 是否已经缓存,如果没有先取出来存到fid_str中,下次再调用的时候该变量已经有值了,不用再去JVM中获取,起到了缓存的作用。

遇到的坑:

但是请注意:cls_string是一个局部引用,与方法和字段 ID 不一样,局部引用在函数结束后会被 JVM 自动释放掉,这时cls_string成为了一个野针对(指向的内存空间已被释放,但变量的值仍然是被释放后的内存地址,不为 NULL),当下次再调用 Java_com_xxxx_newString 这个函数的时候,会试图访问一个无效的局部引用,从而导致非法的内存访问造成程序崩溃。所以在函数内用 static 缓存局部引用这种方式是错误的。

类静态初始化时缓存:

在调用一个类的方法或属性之前,Java 虚拟机会先检查该类是否已经加载到内存当中,如果没有则会先加载,然后紧接着会调用该类的静态初始化代码块,所以在静态初始化该类的过程当中计算并缓存该类当中的字段 ID 和方法 ID 也是个不错的选择。

两种缓存方式比较

如果在写 JNI 接口时,不能控制方法和字段所在类的源码的话,用使用时缓存比较合理。但比起类静态初始化时缓存来说,用使用时缓存有一些缺点:

使用前,每次都需要检查是否已经缓存该 ID 或 Class 引用

如果在用使用时缓存的 ID,要注意只要本地代码依赖于这个 ID 的值,那么这个类就不会被 unload。另外一方面,如果缓存发生在静态初始化时,当类被 unload 或 reload 时,ID 会被重新计算。因为,尽量在类静态初始化时就缓存字段 ID、方法 ID 和类的 Class 引用。

点击详情

2. 自定义View的一个绘制流程(底层)

自定义控件过程

自定义控件的流程大致分为以下几步

定义属性

定义xml文件

自定义View获取属性

onMeasure()

onLayout()

自定义view的目的是为了提升我们的视觉体验,所以一般我们会辅助一些动画来提升体验,为了增强交互,我们也要为其增加一些交互,所以我么需要对其中进行一些事件的监听,自定义监听器,然后在我们需要的地方进行回调,考虑完这些,我们需要再考虑的是如何提高这些view的复用性。

View的绘制流程

OnMeasure

OnLayout

OnDraw

对于自定义View,我们通常会重写这三个方法,重写那些,取决于我们的自定义View从哪里继承,然后要实现什么样的功能。大致归纳有以下几点。

继承View

实现一些不规则的图形,需要重写onDraw方法进行绘制

继承ViewGroup

需要实现对于子控件的测量和布局

继承特定View

较容易实现

继承特定ViewGroup

无需处理测量和布局

点击详情1

点击详情2

3. 非静态内部类为什么会持有外部类的引用

通过反编译的结果, 普通的非static内部类比static内部类多了一个
field: final com.qihoo.browser.OuterClass this$0
;在默认的构造方法中,用外部类的对象对这个filed赋值.

用intellijidea打开
OuterClass$NormallInnerClass.class
, 可以看到内部类调用外部类的方法就是通过这个filed实现的. 这也就是static 内部类无法调用外部类普通方法的原因,因为static内部类中没有这个
field: final com.qihoo.browser.OuterClass this$0
;

解决方法

publicclass MainActivity extends Activity {
privateMyThread mThread;

@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
exampleThree();
}

privatevoid exampleThree() {
mThread = new MyThread();
mThread.start();
}

//static内部类可以避免,持有外部类的引用.
private static class MyThread extends Thread {
private boolean mRunning = false;

@Override
public void run() {
//对一些死循环的耗时操作,需要设置退出线程的标识 flag
mRunning = true;
while(mRunning) {
SystemClock.sleep(1000);
}
}

//定义一个flag 来停止线程的运行.
public void close() {
mRunning = false;
}
}

@Override
protected void onDestroy() {
super.onDestroy();
//activity被销毁的时候关闭线程
mThread.close();
}
}


点击详情1

点击详情2

4. 静态方法为什么不能被重写

非静态方法 按重写规则调用相应的类实现方法,而静态方法只与类相关。

所谓静态,就是在运行时,虚拟机已经认定此方法属于哪个类。

专业术语有严格的含义,用语要准确.”重写”只能适用于实例方法.不能用于静态方法.对于静态方法,只能隐藏(可以重写那只是形式上的 ,并不满足多态的特征,所以严格说不是重写)。

静态方法的调用不需要实例化吧.. 不实例化也就不能用多态了,也就没有所谓的父类引用指向子类实例.因为不能实例化 也就没有机会去指向子类的实例。所以也就不存在多态了。

静态方法不依赖类就可以访问。这就是它的用途啊,没有new对象可调用的方法。然而,重写是依赖对象的。重写父类的某一方法,而static不依赖类。

5. listView放100个布局,如何做优化(全部加载) 想显示就显示,不显示就不显示

善用自定义 View,自定义 View 可以有效的减小 Layout 的层级。

5.1 listView的终极优化(推荐)

包括利用好 ConvertView、利用好 ViewType、Layout 层次结构、ViewHolder、使用自定义布局、保证 Adapter 的 hasStableIds() 返回 true、Item 不能太高、getView() 中要做尽量少的事情、ListView 中元素避免半透明、尽量开启硬件加速、 AnimationCache、 ScrollingCache 和 SmoothScrollbar。

个人收获:

比viewHolder更有效的方式是使用自定义布局,

自定义布局有个好处就是可以省略 ViewHolder。说出来可能你不会信, ViewHolder 首先会占用 setTag() ,其次每次取出后都需要转换一下类的类型。如果是自定义布局的话,findViewById() 这个过程可以在构造函数中进行.

点击详情

6. view和surfaceView的区别

Android游戏开发中主要的类除了控制类就是显示类,比较重要也很复杂的就是显示和游戏逻辑的处理。在J2ME中可以通过Display和Canvas来实现显示,而Android中处理显示的是View类。下面为大家简单介绍
android.view.View
android.view.SurfaceView


SurfaceView是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用SurfaceView,到底有哪些优势呢? SurfaceView可以控制表面的格式,比如大小,显示在屏幕中的位置,最关键是的提供了SurfaceHolder类,使用getHolder方法获取,相关的有
Canvas  lockCanvas()、  Canvas  lockCanvas(Rect dirty)  、void  removeCallback(SurfaceHolder.Callback callback)、void  unlockCanvasAndPost(Canvas canvas)
控制图形以及绘制,而在
SurfaceHolder.Callback
接口回调中可以通过下面三个抽象类可以自己定义具体的实现(比如第一个更改格式和显示画面):

abstract void  surfaceChanged(SurfaceHolder holder, int format, int width, int height) ;
abstract void  surfaceCreated(SurfaceHolder holder) ;
abstract void  surfaceDestroyed(SurfaceHolder holder) ;


对于Surface相关的,Android底层还提供了GPU加速功能,所以一般实时性很强的应用中主要使用SurfaceView而不是直接从View构建,同时后面会讲到的OpenGL中的GLSurfaceView也是从该类实现。


7. 蓝牙

点击详情

8. 说说你比较熟悉的一个开源框架的 (源码流程)

OkHttp + volley

OKHttp的优点

OKHttp是Android版Http客户端。非常高效,支持SPDY、连接池、GZIP和HTTP缓存。

一种开放的网络传输协议,由Google开发),它为你做了很多的事情。

OkHttp实现的诸多技术如:连接池,gziping,缓存等。

OkHttp使用Okio来大大简化数据的访问与存储,Okio是一个增强 java.io 和 java.nio的库。

OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。

OkHttp还处理了代理服务器问题和SSL握手失败问题。

*目前,该封装库志支持:

一般的get请求

一般的post请求

基于Http的文件上传

文件下载

上传下载的进度回调

加载图片

支持请求回调,直接返回对象、对象集合

支持session的保持

支持自签名网站https的访问,提供方法设置下证书就行

支持取消某个请求

Volley

Volley是一个简化网络任务的库。他负责处理请求,加载,缓存,线程,同步等问题。它可以处理JSON,图片,缓存,文本源,支持一定程度的自定义。

Volley在Android 2.3及以上版本,使用的是HttpURLConnection,而在Android 2.2及以下版本,使用的是HttpClient。

Volley存在一个缓存线程,一个网络请求线程池(默认4个线程)。

它的设计目标就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕

Volley的优点很多,可拓展、结构合理、逻辑清晰、能识别缓存、通过统一的方式,获取网络数据,包括且不限于文本、图片等资源。

Volley在一开始创建请求队列的过程中,需要创建网络线程和缓存线程,同时还需要初始化基于Disk的缓存,这中间有大量的资源开销和IO操作,所有才会慢。

9. 现在市面上常用的适配

点击详情

10. 子线程创建的handler ,可以调用应用本身维护的handler的方法吗

一个Handler的创建它就会被绑定到这个线程的消息队列中,如果是在主线程创建的,那就不需要写代码来创建消息队列了,默认的消息队列会在主线程被创建。但是如果是在子线程的话,就必须在创建Handler之前先初始化线程的消息队列。

点击详情

11. fragment 中替换和添加的区别.哪个有优势.

transaction.replace()


使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体

transaction.replace() fragment生命周期会重走.

transaction.add() 当使用add(),show(),hide()跳转新的Fragment时,旧的Fragment回调onHiddenChanged(),不会回调onStop()等生命周期方法,而新的Fragment在创建时是不会回调onHiddenChanged(),这点要切记.

点击详情
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 面试题 jni