Object大小
Object obj = new Object();
obj引用类型占用8 byte大小的栈空间
具体的对象占用的堆空间由对象决定
String拼接
StringBuffer append是线程安全的使用sychronized保证线程同步
StringBuilder 效率高,但是是非线程安全的
String 不可变的对象,每次对String进行操作的时候,都会生成一个新的对象,这会对系统的性能造成影响
StringBuilder和StringBuffer在处理拼接字符串的时候比+=效率高,因为一个是动态拼接,一个是静态拼接。
每次+=""实际是重新开辟了内存空间来填充拼接后的字符串,会导致大量GC
JDK8针对+=""的拼接有做部分优化,在非fori的时候,会根据情况自动转义成StringBuilder/StringBuffer,但是在某些请款下还是不会变成有效的append方式,因此
因此在实际的使用中,当你无法区分字符串是静态拼接还是动态拼接的时候,还是使用StringBuilder/StringBuffer
如果能估算到字符串的长度, 尽可能去指定开辟的内存空间大小
String.intern()
s.intern()方法的时候,可能会导致永久代溢出, 因为会判断值是否存在永久代, 不存在则加入.
随机数Random
Random 虽然是线程安全的,是由于其对应的seed种子采用atomicLong保证了原子性,但是由于采用atomicLong在多线程竞争的时候会有性能损耗降低
SecureRandom 是继承Random的实现,本质上并发时也存在问题,但是随机性比Random好,除了使用系统时间外还使用了鼠标点击,键盘点击等等作为变量因子
ThreadLocalRandom 的SEED是无锁的,并发时不存在性能损耗
Java中的尾递归不支持优化
尾递归定义:
- 调用自身函数(Self-called)
- 计算仅占用常量栈空间(Stack Space)
- 调用在函数结束前最后一行, 只包含函数调用
Java到jdk8还是不支持尾递归(kotlin支持),不支持尾递归而使用了尾递归的写法,会导致深层次的线程棧帧嵌套最后导致stack overflow,以下代码是尾递归写法,在jdk编译
的时候使用的是重复执行对应方法
,在kotlin编译
的时候会将递归改造成fori循环
public static int sum(int start, int end , int acc){
if(start > end){
return acc;
}else{
return sum(start + 1, end, start + acc);
}
}
成员(实例)变量 + 类(静态)变量 + 局部变量
成员变量
- 随着对象创建存在,回收释放
- 只能被对象调用
- 存储在堆内存 heap
- 无初始化
类变量
- 随着类加载存在,类消失消失
- 能被对象/类名调用
- 存储在方法区 method area(共享数据区)
- 无需初始化
局部变量
- 随着线程栈stack frame存在,释放
- 只能在线程栈内部调用
- 存储在栈 thread stack中
- 需要初始化
网友评论