复习

java相关:面试中关于Java你所需知道的的一切

一:架构方面

1、模块化组件化开发架构

一开始使用比较简单的架构 ,界面->逻辑层->工具包层,后面改为分业务模块->工具包,但是业务模块之间存在大量耦合。现在将业务模块再具体划分,比如购物流程模块,地址选择管理模块,消息模块。自己写的router,没有用注解,没有依赖注入,写了大量的映射和接口注册。借鉴阿里的Arouter[Alibaba-ARouter] 新版本解读与控制反转在移动端的应用

Android开发:由模块化到组件化

Arouter:自定义注解

采用arr方式解决重复依赖

采用新的网络请求框架Retrofit+OkHttp,新的图片及下载框架,okhttp,规范了接口定义以及数据加密等。

当然,我们还做了很多的新的尝试,RecycleView替换了ListView,状态栏Immersive Mode设计,组件化开发的尝试,App功能动态化配置,通用自定义控件设计以及国际化设配等。

ARouter的优势:

编译器处理注解产生映射文件,运行期加载映射文件实现路由

Bootstrapping、Extensibility以及Simple & Enough

编译期间:页面自动注册—注解&注解处理器

运行期间:动态加载—–分组管理,按需加载

全局拦截器

依赖注入

运行期动态修改路由

降级问题

2、hybrid架构

① NativeUI组件,header组件、消息类组件

② 通讯录、系统、设备信息读取接口

③ H5与Native的互相跳转,比如H5如何跳到一个Native页面,H5如何新开Webview做动画跳到另一个H5页面

4、数据请求,数据操作的接口,工具包之类

android中通信方式:

1、传统的JavascriptInterface,setJavaScriptEnabled呀小心xss攻击,4.2已修复

2、JSbridge,定义一套协议

3、代码重构的经验

首先讲述自己的工程架构演变,由普通依赖到模块化组件化,路由结构,通信原理,怎样解耦。然后问面试官对中小型公司自己这一套改进有没有什么建议,引用RXjava这类开源框架。提到自己对知识的渴望,然而在小公司人员不足和业务量不庞大的情况体验不到它的好处,特别想进大的平台加深自己对整个架构的优点的深入理解。

4、AOP OOP

面向切面(从左到右的关系,将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装到一个可重用模块,并将其名为“Aspect”)。Android中应用:网络请求,图片操作,数据解析,文件操作,Log,格式转换等共用型Util包。

面向对象:注重上下层,封装、继承和多态性等概念来建立一种对象层次结构,允许你定义从上到下的关系,但并不适合定义从左到右的关系

二:性能优化和内存优化具体经验

Runtime.getRuntime().maxMemory()最大可分配内存

Runtime.getRuntime().freeMemory()当前空闲内存

Runtime.getRuntime().totalMemory()当前占用内存

内存检测工具MemoMonitor,android device monitor

优化:

数据结构的优化(1、StringBuilder拼接;2、SparseArray(2个数组,int型的Key数组,value数组)、ArrayMap(hash值的Key数组,keyvalue成对的数组)(添加、删除、查找数据的时候都是先使用二分查找法得到相应的index)代替HashMap,HashMap初始就会创建容量为16的数组,而且每次都是以2倍的容量递增,SparseArray、ArrayMap;3、内存抖动;4、使用parcelable代替serializebal,serializebal会产生大量临时变量引起GC)

对象复用:列表布局里单Item的复用,避免在ondraw里进行对象的创建

避免内存泄露:内存泄漏会导致heap可用内存越来越少,这时当有一个稍大的内存占用,很可能会造成OOM,还有一点它会让GC频繁的触发造成内存抖动。造成内存泄漏的一些点:单例使用了context(使用applicationcontext),匿名内部类,handler,static变量,资源未关闭(io流,cursor使用了一定要及时关闭),asyntask,耗时操作可以考虑使用service

OOM优化:大部分是图片造成的。使用软引用弱引用;临死bitmap的及时回收;某些大内存分配时可以使用try/catch,即使失败了也不会崩溃;加载bitmap时注意(缩放比例、解码格式ARGB_4444、局部加载),LUR cache

三:用到的开源框架原理

okhttp原理:

首先使用建造者模式构建request,然后经过一系列拦截器(包括跟服务器桥接的响应BridgeInterapter,CacheInterapter,ConnectInterapter,Callserver),拦截器连成了一条链InterappetChain.底层用了okio连接,socket。异步请求做了一个线程池的封装。

多路复用机制(nextconnection从connection池里获取到的话,就复用,获取不到才create),重连机制(判断是否能onresponce,获取不到则recovery,循环)

支持HTTP2/SPDY黑科技

socket自动选择最好路线,并支持自动重连

拥有自动维护的socket连接池,减少握手次数

拥有队列线程池,轻松写并发

拥有Interceptors轻松处理请求与响应(比如透明GZIP压缩,LOGGING)

实现基于Headers的缓存策略

volley原理,

glide原理

glide .with(context):所有request请求是通过requestmanagerrechiver这个类把requestmanager绑定到activity或fragment类。创建了一个fragment把requestmanager传给fragmengt,与activity生命周期绑定

.load(url) : 创建DrawableTypeRequest,添加一系列条件初始化

.into里面将imageview与lifecycle生命周期关联了起来,里面的核心是一个引擎类Engine,里面有个Load,先从缓存中读取,Engine中包含LruCache缓存及一个当前正在使用的active资源Cache(弱引用),Cache优先级LruCache>activeCache,从LruCache取出使用了则会放到activeCache,缓存没有则通过线程池去获取图片,Engine在初始化时要传入两个ExecutorService,即会有两个线程池,一个用来从DiskCache获取resource,另一个用来从Source中获取(通常是下载)。先进入DiskCacheService中执行获取,如果没找到则进入SourceState,进到SourceService中执行下载。

Glide的Target:

负责图片加载的回调中

4.4以前是Bitmap复用必须长宽相等才可以复用

4.4及以后是Size>=所需就可以复用,只不过需要调用reconfigure来调整尺寸

Glide用AttributeStategy和SizeStrategy来实现两种策略

图片池在收到传来的Bitmap之后,通过长宽或者Size来从KeyPool中获取Key(对象复用到了极致,连Key都用到了Pool),然后再每个Key对应一个双向链表结构来存储。每个Key下可能有很多个待用Bitmap

取出后要减少图片池中记录的当前Size等,并对Bitmap进行eraseColor(Color.TRANSPAENT)操作确保可用

butterknife原理

四:Framework层常用模块原理

AMS和WMS原理

audioflinger原理,

整个音频系统的核心与难点,启到承上(为上层提供访问接口)启下(通过HAL来管理音频设备)的作用。

audiotrack原理,

播放声音,2种模式,AudioTrack中有MODE_STATIC和MODE_STREAM两种分类。STREAM的意思是由用户在应用程序通过write方式把数据一次一次得写到audiotrack中。这个和我们在socket中发送数据一样,应用层从某个地方获取数据,例如通过编解码得到PCM数据,然后write到audiotrack。

这种方式的坏处就是总是在JAVA层和Native层交互,效率损失较大。

而STATIC的意思是一开始创建的时候,就把音频数据放到一个固定的buffer,然后直接传给audiotrack,后续就不用一次次得write了。AudioTrack会自己播放这个buffer中的数据。

这种方法对于铃声等内存占用较小,延时要求较高的声音来说很适用。

vold框架原理,

1,有一个netlinkmanager接收来自Linux内核的uevent消息,例如sd卡的插拔会引起kernel向NM发送uevent消息,

2,netlinkmanager将这些消息转发给volumeManager,volumeManager做一些操作后将消息通过CommandListener发送给MountService.MountService收到消息后做进一步处理。比如volumeManager----disk insert-----MountService----Mount----Vold,表示挂载这个SD卡

4,CommandListener内部封装了一个socket用于跨进程通信,在vold进程中属于服务端,接收来自mountservice的控制命令,同时volumeManager和netlinkmanager又通过它发送消息给MountService

dhcp协议

binder原理:

传统·IPC·:需要做两次拷贝:用户空间->内核空间->用户空间

binder:由Binder驱动负责管理数据接收缓存,驱动会根据发送数据包的大小,使用最佳匹配算法从缓存池中找到一块大小合适的空间,将数据从发送缓存区复制过来,mmap()分配的内存是映射在接收方用户空间里的.为了实现用户空间到用户空间的拷贝,mmap()分配的内存除了映射进了接收方进程里,还映射进了内核空间。所以调用copy_from_user()将数据拷贝进内核空间也相当于拷贝进了接收方的用户空间,这就是Binder只需一次拷贝的‘秘密’。

五:android重要知识点

Android开发--如何减小Apk文件的大小


静态编译和动态编译

静态 include $(BUILD_STATIC_JAVA_LIBRARY)

动态 include $(BUILD_JAVA_LIBRARY)

a、可以在apk的Android.mk中去添加动态jar包的依赖,使用的时候jar包的类可以直接调用

b、apk编译的时候如果不在android.mk中做动态jar包的依赖的话,可以在使用的时候去动态寻找system/framework/SkyFramework的jar包,去load此jar包,在去找jar包中的   class;这种方法 apk中可以直接调用接口中自己定义的方法,编译时不需要去做android.mk的依赖。 实现的地方直接继承接口即可,打包到动态jar包中。

这样可以实现分离,接口的定义和实现做到分离,在开发阶段非常有用,不同部门直接可以并行进行。

网络编程,服务器端编程

安卓中Fragment应用,相比Activity的好处

Fragment可以使你能够将activity分离成多个可重用的组件,每个都有它自己的生命周期和UI。

Fragment可以轻松得创建动态灵活的UI设计,可以适应于不同的屏幕尺寸。从手机到平板电脑。

Fragment是一个独立的模块,紧紧地与activity绑定在一起。可以运行中动态地移除、加入、交换等。

Fragment提供一个新的方式让你在不同的安卓设备上统一你的UI。

Fragment 解决Activity间的切换不流畅,轻量切换。

Fragment 替代TabActivity做导航,性能更好。

Fragment 在4.2.版本中新增嵌套fragment使用方法,能够生成更好的界面效果。

Fragment做局部内容更新更方便,原来为了到达这一点要把多个布局放到一个activity里面,现在可以用多Fragment来代替,只有在需要的时候才加载Fragment,提高性能。

可以从startActivityForResult中接收到返回结果,但是View不能。

recyclerview的复用原理

热修复原理

android7.0原理--签名机制:

android 7.0中引入了APK Signature Scheme V2(Full APK Signature),而V1(jar Signature) 来自JDK;

V1:仅验证未解压的文件内容,这样APK 签署后可进行许多修改 ,可以移动甚至重新压缩文件;

V2:验证压缩文件的所有字节,而不是单个 ZIP 条目,因此,在签名后无法再更改(包括 zipalign)。正因如此,现在在编译过程中,我们将压缩、调整和签署合并成一步完成。好处显而易见,更安全而且新的签名可缩短在设备上进行验证的时间(不需要费时地解压缩然后验证),从而加快应用安装速度。如有任何自定义任务篡改 APK 文件或对其进行后处理(无论以任何方式),那么V2 签名会有作废的风险,从而导致您的 APK 与 Android 7.0 及更高版本不兼容。


六:android重要知识点

java类加载机制

类加载的过程包括了加载(查找并加载类的二进制数据)、验证(确保被加载的类的正确性:确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全)、准备(为类的静态变量分配内存,并将其初始化为默认值,public static int value = 3,这是设为0)、解析(把类中的符号引用转换为直接引用)、初始化(类的静态变量赋予正确的初始值,JVM负责对类进行初始化,主要对类变量进行初始化)五个阶段。

解析阶段则不一定,它在某些情况下可以在初始化阶段之后开始,这是为了支持Java语言的运行时绑定(也成为动态绑定或晚期绑定)

类加载器:双亲委派模型,如果存在父类加载器,就委派给父类加载器加载,如果不存在父类加载器,就检查是否是由启动类加载器加载的类,通过调用本地方法,如果父类加载器和启动类加载器都不能完成加载任务,才调用自身的加载功能。

意义:系统类防止内存中出现多份同样的字节码,-保证Java程序安全稳定运行

java编译过程

分析和输入到符号表

注解处理

语义分析和生成class字节码文件

GC

final用法,反射原理

反射:先讲反射机制,反射就是程序运行期间JVM会对任意一个类洞悉它的属性和方法,对任意一个对象都能够访问它的属性和方法。依靠此机制,可以动态的创建一个类的对象和调用对象的方法。

其次就是反射相关的API,只讲一些常用的,比如获取一个Class对象。Class.forName(完整类名)。通过Class对象获取类的构造方法,class.getConstructor。根据class对象获取类的方法,getMethod和getMethods。使用class对象创建一个对象,class.newInstance等。

最后可以说一下反射的优点和缺点,优点就是增加灵活性,可以在运行时动态获取对象实例。缺点是反射的效率很低,而且会破坏封装,通过反射可以访问类的私有方法,不安全。

注解原理

io,nio区别和原理,NIO中select的实现机制

Java IO是面向流的,这意味着我们需要每次从流中读取一个或多个字节,直到读取完所有字节;NIO是面向缓冲的,也就是说会把数据读取到一个缓冲区中,然后对缓冲区中的数据进行相应处理。

Java IO是阻塞IO,而NIO是非阻塞IO。

Java NIO中存在一个称为选择器(selector)的东西,它允许你把多个通道(channel)注册到一个选择器上,然后使用一个线程来监视这些通道:若这些通道里有某个准备好可以开始进行读或写操作了,则开始对相应的通道进行读写。而在等待某通道变为可读/写期间,请求对通道进行读写操作的线程可以去干别的事情。

多线程同步的几个方式及区别

1、synchronized (托管给JVM执行的),2、重入锁(retrandlock,读写ReentrantReadWriteLock)3、volatile关键字,阻塞队列(linkedblockingqueen),是java代码自己实现的,4、局部变量(ThreadLocal,提到Looper.prepare)5、使用同步容器(vector,hashtable,ConcurrentHashMap),6、CountDownLatch

乐观锁和悲观锁的区别

悲观锁,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

synchronized是基于悲观锁,比较适用于大量线程频繁请求,lock是乐观锁,适用于不是很频繁的

ReentrantLock非中断锁(一直等待)和中断锁(lock.lockInterruptibly()),得到中断响应则中断,还提供公平锁及非公平锁。

stringbuffer和stringbuilder区别

stringbuffer是线程安全,适合多线程操作字符串,stringbuilder是非线程安全的,适合单线程大量操作字符串,在单线程中的性能比StringBuffer高

Java重写hashCode(),equals()函数的时机

虽然 a 与 b不是同一个对象,但是你希望无论使用 a 还是 b 都可以从map中取出相同的 value,也就是你会认为 a 与 b 的内容是相同的,就是当把他们作为索引值,或者在 set 中不会重复出现,这些情况适用于重写他们。重写equals一定要重写Hashcode,这是java规定的。如果不满足这个条件则map, set等的处理会出现错误的。

get()和post()区别

语义的区别,设计不同,get是为请求,post是提交改变服务器状态

1. GET使用URL或Cookie传参。而POST将数据放在BODY中。

2. GET的URL会有长度上的限制,则POST的数据则可以非常大。

3. POST比GET安全,因为数据在地址栏上不可见。

成员变量的类型

静态变量,实例变量,final修饰的常量

七:数据结构算法相关

如何判断一个链表中存在环

1遍历做标记,2:便利把指针反转,如果走到开始就有环,3:双指针 一个一次走一步,一个一次走两步

各排序、冒泡排序、二分查找思想原理

二叉树

问1000坛酒,里面有1坛毒酒,需要多少只老鼠才能判断出毒酒是哪坛?

都转为二进制 2的10次方为1024,10只老鼠


Linux中查看内存使用状况命令?查看网络状况?

cat/proc/meminfo  free

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容