Android进阶–int和Integer的理解

今天早高峰在地铁上突然有一个疑惑:String 是immutable是为了保证线程安全,Integer也是Immutable,为什么并发的时候建议使用AtomicInteger呢?

晚上回来查阅相关资料得出总结:

1
2
3
4
5
6
7
8
9
10
11
12
13
String a="test";
String b="test";
System.out.println(a==b);
System.out.println(System.idntityHashCode(a));
System.out.println(System.identityHashCode(b));
输出:true
851664923
851664923
//为什么有觉得可变呢?
String a="test";
a="test1"

a就变成了test1,其实在这里是新建了一个”test1”字符串对象(如果常量池没有这个值的话就是新建)。然后将变量引用指向它。注意:这里并没有修改”test”这个变量的内部状态,”test”这个字符串对象是线程安全的
除非你用final修饰,否则所有的变量指向都是可变的。
这种情况下要保证线程安全性:

  • 可以考虑使用volatile确保可见性。
  • 可以使用final修饰
  • 你可以使用AtomicReference之类的原子对象,对于Integer等也有AtomicInteger之类的
  • 对相应代码区域加锁

有兴趣可以查看这两篇文章:
String是线程安全的吗?那String岂不是不能进行同步?
Java多线程系列–“JUC原子类”04之 AtomicReference原子类

综上:String Immutable为了线程安全知识相对的(字符串常量值不可变),但是引用可变,所以为了并发的时候线程安全,可以使用上面所说的几种方案。(如果有更好的认识深度,欢迎讨论)有兴趣可以查看我之前写的一篇文章关于介绍:String为什么是final修饰的

问题:

  • int和Integer有什么区别?谈谈Integer的值缓存范围?

知识点

  1. Integer缓存或者String 常量池缓存用到的设计模式-享元模式。

image

相关代码(好记性不如烂笔头,代码是最好的理解):

1
2
3
4
5
6
7
8
9
package yonghui.cn.firstthread.flyweight;
/**
* 作者:huangchen on 2018/7/26 20:57
* 邮箱:huangchen@yonghui.cn
*/
public interface IBike {
void biliing(int time);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package yonghui.cn.firstthread.flyweight;
/**
* 作者:huangchen on 2018/7/26 20:58
* 邮箱:huangchen@yonghui.cn
*/
public class ShareBike implements IBike {
private int price;//单价
private int total;//总价
@Override
public void biliing(int time) {
System.out.println("total price is" + price * time);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package yonghui.cn.firstthread.flyweight;
import java.util.HashMap;
/**
* 作者:huangchen on 2018/7/26 20:11
* 邮箱:huangchen@yonghui.cn
*/
public class FlyWeightFactory {
private HashMap<String, IBike> map = new HashMap<>();
public IBike getIBike(String name) {
IBike iBike;
if (map.containsKey(name)) {
System.out.println("押金已经交过了" + name);
iBike = map.get(name);
return iBike;
} else {
System.out.println("押金没有交,开始交押金299元");
iBike = new ShareBike();
map.put(name, iBike);
return iBike;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package yonghui.cn.firstthread.flyweight;
/**
* 作者:huangchen on 2018/7/26 20:16
* 邮箱:huangchen@yonghui.cn
*/
public class Client {
public void test(){
FlyWeightFactory flyWeightFactory = new FlyWeightFactory();
IBike ofo = flyWeightFactory.getIBike("ofo");
ofo.biliing(2);
IBike mobike = flyWeightFactory.getIBike("mobike");
mobike.biliing(1);
IBike ofo1 = flyWeightFactory.getIBike("ofo");
ofo1.biliing(3);
}
}

关于享元模式有兴趣可以参考:Android的设计模式-享元模式

  1. 自动装箱、自动拆箱发生在编译阶段。静态工厂方法valueof()使用了缓存机制,自动装箱的时候,缓存机制起作用。实际开发中,避免无意的装箱、拆箱行为(不管是内存使用还是运行速度、10w个Java对象比10w整数的开销要大得多,光是对象头空间占用已经是数量级的差距了)。
  2. 对象的内存结构:对象由对象头、对象实例、对齐填充三部分组成。具体有兴趣可以参考:Java对象内存布局

    回答问题:

    int是我们常说的整形,是八大基本数据类型之一,占4个字节,取值范围2的31次方减去1,Java需要号称一切都是对象,但是基本数据类型是个例外。

    Integer是int对应的包装类,他有一个int类型存字段(private final修饰,Immutable),并且提供了基本操作,比如数字运算、int和字符串之间的转换。在Java5中,引入了自动装箱、拆箱功能。Java根据上下文,自动进行转换,极大简化了相关编程。

    关于Integer的值缓存,这涉及Java5的内一个改进。大部分数据操作都集中在有限的、较小的数值范围,因而,在Java 5 中新增了静态工厂方法valueof,在调用它的时候会利用一个缓存机制,带来了明显的性能改进。按照Javadoc,这个值默认缓存-128-127之间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//Integer部分源码
//Immutable private final
/**
* The value of the {@code Integer}.
*
* @serial
*/
private final int value;
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

参考:

声明:此为原创,转载请联系作者


作者:微信公众号添加公众号-遛狗的程序员 ,或者可以扫描以下二维码关注相关技术文章。

qrcode_for_gh_1ba0785324d6_430.jpg
当然喜爱技术,乐于分享的你也可以可以添加作者微信号:

WXCD.jpeg

文章目录
  1. 1. 问题:
  2. 2. 知识点
  3. 3. 回答问题:
|