从接触java至今日已经一年有余,从今日开始每日总结一些遇到的问题及其解决方法,用以回顾备忘。
1. 0.1*3 == 0.3 ?
结果为:false
浮点数加法会出现精度问题,正确做法可以参考下文,建议是先转为int 做完运算后再还原。
https://blog.csdn.net/haihuan2004/article/details/52900909
2. Java 中的构造器链是什么?
多个构造方法,少参数的加上默认参数调用复杂参数的,这一现象在各开源框架中常见。
以对象池org.apache.commons.pool.impl.GenericObjectPool<T> 为例,共有N个构造器,简单构造器添加相应的默认参数调用复杂构造器:
public class GenericObjectPool<T> extends BaseObjectPool<T> implements ObjectPool<T> {
ate a new <tt>GenericObjectPool</tt> with default properties.
*/
public GenericObjectPool() {
this(null, DEFAULT_MAX_ACTIVE, DEFAULT_WHEN_EXHAUSTED_ACTION, DEFAULT_MAX_WAIT, DEFAULT_MAX_IDLE,
DEFAULT_MIN_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE);
}
public GenericObjectPool(PoolableObjectFactory<T> factory) {
this(factory, DEFAULT_MAX_ACTIVE, DEFAULT_WHEN_EXHAUSTED_ACTION, DEFAULT_MAX_WAIT, DEFAULT_MAX_IDLE,
DEFAULT_MIN_IDLE, DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE);
}
public GenericObjectPool(PoolableObjectFactory<T> factory, GenericObjectPool.Config config) {
this(factory, config.maxActive, config.whenExhaustedAction, config.maxWait, config.maxIdle, config.minIdle,
config.testOnBorrow, config.testOnReturn, config.timeBetweenEvictionRunsMillis,
config.numTestsPerEvictionRun, config.minEvictableIdleTimeMillis, config.testWhileIdle,
config.softMinEvictableIdleTimeMillis, config.lifo);
}
public GenericObjectPool(PoolableObjectFactory<T> factory, int maxActive) {
this(factory, maxActive, DEFAULT_WHEN_EXHAUSTED_ACTION, DEFAULT_MAX_WAIT, DEFAULT_MAX_IDLE, DEFAULT_MIN_IDLE,
DEFAULT_TEST_ON_BORROW, DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
DEFAULT_NUM_TESTS_PER_EVICTION_RUN, DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE);
}
public GenericObjectPool(PoolableObjectFactory<T> factory, int maxActive, byte whenExhaustedAction, long maxWait) {
this(factory, maxActive, whenExhaustedAction, maxWait, DEFAULT_MAX_IDLE, DEFAULT_MIN_IDLE, DEFAULT_TEST_ON_BORROW,
DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE);
}
public GenericObjectPool(PoolableObjectFactory<T> factory, int maxActive, byte whenExhaustedAction, long maxWait,
boolean testOnBorrow, boolean testOnReturn) {
this(factory, maxActive, whenExhaustedAction, maxWait, DEFAULT_MAX_IDLE, DEFAULT_MIN_IDLE, testOnBorrow,
testOnReturn, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE);
}
public GenericObjectPool(PoolableObjectFactory<T> factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, DEFAULT_TEST_ON_BORROW,
DEFAULT_TEST_ON_RETURN, DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE);
}
public GenericObjectPool(PoolableObjectFactory<T> factory, int maxActive, byte whenExhaustedAction, long maxWait,
int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn,
DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, DEFAULT_TEST_WHILE_IDLE);
}
public GenericObjectPool(PoolableObjectFactory<T> factory, int maxActive, byte whenExhaustedAction, long maxWait,
int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis,
int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn,
timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
}
public GenericObjectPool(PoolableObjectFactory<T> factory, int maxActive, byte whenExhaustedAction, long maxWait,
int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis,
int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, minIdle, testOnBorrow, testOnReturn,
timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle,
DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
}
3. Switch 中使用 String 注意项:
从 Java 7 开始,我们可以在 switch case 中使用字符串,但这仅仅是一个语法糖。内部实现在 switch 中使用字符串的 hash code。
4. WeakHashMap 常用场景?
因为当key对象不在被引用时,key / value 会被清楚,适用于请求进入后的该笔数据暂存,在处理线程使用完毕后清除,非常适用于缓存。
5. Objcet 的 hashcode 与 equal 函数原理?
对象equal 常用于字符串比较,对象比较时,对应元素比较 建议重写。重写的同时也重写hashcode。
6. poll() 方法和 remove() 方法的区别?
poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。
7. 两个数字交换,不使用temp内存?
a' = a^b 此时求出的是a与b不相同的部分 a'代表着a与b 2进制中不相同的位
b = b^a' 此时将b与a' 2进制中不相同的位求反 于是b变成了 a。
a = b^a 此时将b 中与a'不相同的位求反 于是 b^a' 变为了原本的a。
8. a = a + b 与 a += b 的区别
+= 隐式的将加操作的结果类型强制转换为持有结果的类型。如果两这个整型相加,如 byte、short 或者 int,首先会将它们提升到 int 类型,然后在执行加法操作。
9. 对于对象的成员中有对象时,成员需要拷贝。
class A {
private int b = 1;
private String c = "1";
private Object d = new Object a;
private Object clone() {
A a = new A();
a.d = d.clone();
return a;
}
}
10. 缓存淘汰算法--LRU算法
固定大小的LinkedHashMap,removeEldestEntry触发移除key的 当前size大于了设置的缓存大小 。
或者采用hashmap,命中+1,当当前map的容量大于一定时,扫描全部key的value 取最小的移除。
还有个更快现成的,使用redis.......
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Map;
/**
* 类说明:利用LinkedHashMap实现简单的缓存, 必须实现removeEldestEntry方法,具体参见JDK文档
*
* @author dennis
*
* @param <K>
* @param <V>
*/
public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
private final int maxCapacity;
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private final Lock lock = new ReentrantLock();
public LRULinkedHashMap(int maxCapacity) {
super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
this.maxCapacity = maxCapacity;
}
@Override
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
return size() > maxCapacity;
}
@Override
public boolean containsKey(Object key) {
try {
lock.lock();
return super.containsKey(key);
} finally {
lock.unlock();
}
}
@Override
public V get(Object key) {
try {
lock.lock();
return super.get(key);
} finally {
lock.unlock();
}
}
@Override
public V put(K key, V value) {
try {
lock.lock();
return super.put(key, value);
} finally {
lock.unlock();
}
}
public int size() {
try {
lock.lock();
return super.size();
} finally {
lock.unlock();
}
}
public void clear() {
try {
lock.lock();
super.clear();
} finally {
lock.unlock();
}
}
public Collection<Map.Entry<K, V>> getAll() {
try {
lock.lock();
return new ArrayList<Map.Entry<K, V>>(super.entrySet());
} finally {
lock.unlock();
}
}
}
11. 在List移除元素的时候,List 的get(i) 和 for each
更建议使用for each..因为移除了一个元素后,List下标会产生变化。
12. Mybatis的代理类,想要在创建时截获其在spring中id,其名字为类名首字母大写 与其他spring类默认名不同。
其他第三方框架注入sping时,其默认的id为类名小写开头的驼峰命名原则。 例如testService。
而mybatis 注入sping时的默认id为大写开头。
例为: TestDao$312451
这个问题在监听spring容器创建mybatis类时,想在外面添加装饰器,捕获该类老失败。发现命名不同。
13. Mybatis如果实现了事务,事务的注解在接口上时,那么注意了,注入该类的实现时,一定要以接口的方式注入,否则会报类类型转换失败。因为mybatis注入的是代理sun.proxy 而不是你原本实现该事务接口类的类型。
interface A {
@Transactional(value = "transactionManager", isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
void test(@ShardParam("dbParam") RecordOrderDto recordOrderDto, List<TicketDto> ticketDtos)
throws RecorderException;
}
@Service("b")
class B implements A {
@Autowired
prvaite interfaceDao dao;
public void test() {
dao.insert()
}
}
class c {
/**
*这种注入方式会报类型错误
*
/
@Autowired
private B b;
/**
* 正确做法
/
@Autowired
@Qualifier("b")
private A b;
}
14 HashTable 与 HashMap ,很多总说HashTable线程不安全,HashMap 线程安全,是这样的吗
HashTable 已经不推荐使用了,不使用。
ConcurrentHashMap 采用了分段锁。get和put是原子操作,所以线程安全。
HashMap的每个节点与ConcurrentHashMap 的每个分片下的节点,在jdk1.8之后改为了红黑树。
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
无论采用这两种结构,在使用读取变量修改填回时,一定要在外面加锁。
例如:
get(a)
value a=a+1
put(a)
因为HashMap仅仅保证get 和put是原子操作,但是由于多并发下,这种从map中读值再修改填写回去的时候,会出现覆盖。
15. HashMap与ConcurrentHashMap 在其他地方看到,在多线程下并发下,会因为resize导致死锁,所以给这种map在初始化时,添加一个好的初始值,让数据均匀分布,减少扩容的次数是非常好的习惯。
不知道扩容这个导致两个线程同时rehash导致的循环链表死锁问题在jdk1.8.0里面修复没有,目前采用红黑树,应该没有了才对。待验证~~!!!
参考文章:https://blog.csdn.net/V_Axis/article/details/78604505
16. java 32位虚拟机和64位虚拟机中的int
没有区别 int都是32位的,但是因为寻址地址从32->64堆大小根据虚拟机支持 可以调到很大很大了,不过32位项目迁移64位时,因为帧大小的扩充会占用缓存大增,记得调节jvm的UseCompressedOops进行指针压缩,减少缓存。
参考文章:https://blog.csdn.net/zjerryj/article/details/77206928
17. 什么是内存屏障(Memory Barrier)?
内存屏障(memory barrier)是一个CPU指令。基本上,它是这样一条指令: a) 确保一些特定操作执行的顺序; b) 影响一些数据的可见性(可能是某些指令执行后的结果)。编译器和CPU可以在保证输出结果一样的情况下对指令重排序,使性能得到优化。插入一个内存屏障,相当于告诉CPU和编译器先于这个命令的必须先执行,后于这个命令的必须后执行。内存屏障另一个作用是强制更新一次不同CPU的缓存。
个人:在这个命令前所以命名必须执行完,防止重排序的坑,同时强制更新cpu缓存。
18. 计算无符号32位数中,2进制中1的个数。
一篇非常有趣的文档:https://www.cnblogs.com/graphics/archive/2010/06/21/1752421.html