1.java char
占两个字节
unicode 字符集 不是编码,类似于ASCII码
char 不存utf-8,而是存utf-16
utf-8 占1~3个字节
字符串长度与字符数不相等
2.java String
最大长度
字面量,代码中,栈 字节码,65535 javac 65534 kt正常
读文件,堆 虚拟机指令newarray Integer.MAX_VALUE 内存大小限制
3.java匿名内部类限制
匿名内部类有名字的,只是我们看不太懂 xx.xx.xx$1
匿名内部类的继承结构
匿名内部类的构造方法
SAM类型 只能是接口,并且只能有一个方法
4.java方法分派
方法分给谁
静态分派 重载 编译的时候确认,根据调用者的声明类型和参数的类型
动态分派 覆写 运行的时候,根据实际的类型来分派
Groovy 根据实际的类型调用哪个方法
5.java 泛型
类型擦除 与C#对比
类型擦除后为Object,所以不兼容基本数据类型
基本类型无法作为实参,只能引用装箱,拆箱,需要有开销
泛型类型无法用作方法重载
无法当做真实的类型使用
java选择类型擦除主要考虑到了兼容问题
擦除后,在一定场景下可以通过反射获得泛型类型签名信息
Gson Retrofit
6.onActivityResult
实际中怎么使用
使用的时候有哪些不好的地方
能否用回调来替代
自己设计一个方案来替代onActivityResult
7.线程的终止
线程的stop都被废弃了 因为不安全
boolean标志位
interrupt
8.线程安全
可变资源(内存)线程间共享
不变,即安全
可见,能正常处理,也会安全
原子性,每一个指令都没有争议
禁止指令重排序
9.ConcurrentHashMap
如何支持并发
HashTable 整个都加锁,线程安全,暴力,影响效率
JDK1.5,引入段,分段锁,给段加锁,但hash散列值不均匀,会退化成HashTable
JDK1.6,优化散列值不均匀的问题
JDK1.7,之前的16个段都直接初始化了,这个版本的段延迟初始化,用到哪个初始化哪个,并对数组使用volatile,保证段的可见性
JDK1.8,没有分段锁,直接给table使用volatile
10.AR 和 ARFU
AtomicReference 和 AtomicReferenceFiledUpdater 保证原子性,作用于线程安全
AtomicReference 比较消耗内存,每个实例需要额外开辟空间存储一些信息 一般用在实例化较少的场景
AtomicReferenceFiledUpdater 不用额外开辟一些空间,但使用起来比较不友好,一般用于静待对象
11.异步
不是按照顺序执行代码,可以是在同一线程
当回调嵌套态度,就会出现回调地狱,看起来累
引入RxJava,扁平化,解决嵌套,但要注意异常处理和取消处理的操作
Kotlin协程异步同步化,看起来和同步产不多,还是要注意异常与取消 的处理
12.CPU架构 适配
native开发关注
mips 废弃
x86 废弃
armeabi 兼容性最好
armeabi-v7a
arm64-v8a
机器根据自身对应的cpu架构,查找对应的目录so库,因此提供so要提供一整套,要么某一个架构下一个也不提供
兼容也会出现一些问题
提供合适的架构(一个目录),里面也可以放入其他架构的so库,使用时使用动态加载(动态识别机器的cpu架构)
线上监控,根据实际数据来判断哪些应该使用动态加载其他架构的so库
云端下载
so库体积优化
默认隐藏所有符号,只公开必要的
禁用 C++ Exception RTTI,会增加so库大小,Android一般用不了
iostream尽量不使用,尽量使用Android log
使用gc-sections 去除无用代码,类似java中的proguard混淆
构建时分包,不同架构只有相应的so库,依靠应用商城,用户下载 时下载相应cpu架构下的ap
13.java native方法和native函数的绑定
静态绑定 命令规则映射
java包名的点替换成下划线
native方法中需要有修饰符号 避免 C++编译的时候把名字给搞乱了,找不到函数
动态绑定 通过jni函数注册 NativeRegister
在动态 绑定之前调用,还是走静态绑定方式
动态绑定后,走动态绑定方式,可以取消绑定,恢复静态绑定方式,比较灵活
比较
函数名 动态绑定无要求,静态绑定有命名规则
可见性 动态绑定无要求,静态绑定需要明文符号修饰,可见
动态更换 动态绑定可以替换,静态绑定写死的,更换不了
调用性能 动态绑定无需查找,静态绑定需要查找,有额外开销
开发体验 动态绑定没啥副作用,静态绑定重构的时候比较繁琐
AS的支持 动态绑定没法自动关联,静态绑定可以关联,可以点击跳过去,开发时方便查看
14.jni数据传递
通过long类型传递底层对象指针给java层
注意string的几组函数操作的区别于适用场景
GetStringUTFChars/ReleaseStringUTFChars const char * MUTF-8 \0编码成两个字节,避免C字符的结尾
GetStringChars/ReleaseStringChars const jchar* jni函数自动处理字节序转换
GetStringUTFRegion/GetStringRegion 拷贝一部分字符串出来
GetStringCritical/ReleaseStringCritical GC停掉,回收不了这一块内存
注意对象数组较大时的LocalRef超过上限的问题
注意使用DirectBuff时字节序的问题
15.捕获native异常
捕获系统sig信号来捕获native异常
使用JniEnv的findClass 堆栈的classLoader
Native线程绑定到jvm 有内存泄露问题
java对象全局引用 获取到的都是LocalRef,需要新建一个全局
Native调用Java方法 反射
异常回调到java层
16. 其他native语言
Golang
Kotlin native
@CName
静态绑定
动态绑定