1.数值溢出
long num = 5000 * 165 * 24 *3600 *1000
输出结果会溢出,因为整数相乘已经大于了最大的限制,可以采用 在第一个数之后加L的方式先转成long类型
long num = 5000L * 165 * 24 *3600 *1000
p.s.int类型的范围
int max=2147483647
int min=-2147483648
Q:两个正数相乘怎么得到一个负数
E:相乘结果超过int范围结果为负
int i = 1000000;
System.out.println(i*i);
-----------------------
-727379968
-----------------------
的合理解释和过程应该是这样的:
i设置为1000000,在乘方时Java发现结果(1000000000000)已经超出了int基本数据类型的最大范围(2147483647),于是作了默认的类型提升(type promotion),中间结果做为long类型存放,返回结果时目标数据类型int不能够容纳下结果,于是根据Java的基础类型的变窄转换(Narrowing primitive conversion)规则,把结果宽于int类型宽度的部分全部丢弃,也就是只取结果的低32位,于是就得到了上面的结果。
下面用一个十六进制表示的例子阐释这个问题
int i3 = 1000000;
System.out.println (Long.toHexString (i3*i3).toUpperCase());
System.out.println (Long.toHexString (i3*i3).toUpperCase());
System.out.println (Integer.toHexString (i3*i3).toUpperCase());
System.out.println ((int)i3*i3);
---------------------------------------------------
FFFFFFFFD4A51000
1000000000000
D4A51000
-727379968
---------------------------------------------------
2.包装类
为了面对对象而出现
提供了实用的方法: Integer.parselint Integer.toString (类型转换)
集合不允许存放基本数据类型数据,存放数字时,要用包装类型
有时候一个函数需要传递一个Object变量 而你想传递int类型的进去显然不行,这就要用到包装类
包装类默认为null , 在转换的时候,如Integer转int ,需要判断是否为空的情况.
3.精度的丢失
double a = 0.58;
long b = (long)(a * 100);
logger.info("b = {}" , b); // b = 57
输出57 原因是0.58的精度不准确 计算机中存储的是0.57999999999...主要的数
BigDecimal a = BigDecimal.valueOf(0.580);
BigDecimal b = new BigDecimal("0.580");
System.out.println(a); //0.58
System.out.println(b); //0.580
使用BigDecimal的方法就可以保证精度
System.out.println(a.equals(b)); // false
System.out.println(a.compareTo(b)); // 0 (相等)
eq比较数值和精度 而compare只比较数值
equals 基类Object的方法 需重写比较来内容,通常有必要一起重写 hashCode 方法 (第一个参数不能为Null,括号中的可以)
Objects.equal(a,b) //没有null的限制
== 对比两个对象基于内存引用
compareTo 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
Hsahcode
在Object类中,hashCode()返回的并不是对象在内存中的物理存储地址,是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值
用于对象运行过程中,识别对象 同一个对象在运行期,哈希值不变
使用hashcode比较的话比equals快
BigDecimal无法存储无限小数 可以使用MathContext.DECIMAL64 限制位数
4.Strings & Ints 方法
String a = "12abc";
String b = "123bc";
Strings.isNullOrEmpty(a);
Strings.nullToEmpty(a);
Strings.commonPrefix(a,b);
Strings.commonSuffix(a,b);
Strings.padStrat(a,5,'0');
Strings.repeat(a,10); //copy 10份 加在一起输出
Ints.compare(1,2);
Ints.contains(new int[] {1,2,3} , 1);
int[] array = new int[] {1,2,3};
Ints.asList(array); //return List<Integer>
Arrays.asList(array); // return List<int[]> --> get(0) = [1,2,3]
Ints.asList() 得到的List 不支持add方法 使用会抛出异常
List<Integer> list = Ints.asList(array);
list.add(1);
----------------------------------------
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
如需要使用add 则需要重新new成ArrayList
list = new ArrayList<>(list);
WIKI:
引入一个思考为什么asList得到的是一个不可变的List,对源码进行分析:
public static List<Integer> asList(int... backingArray) {
if (backingArray.length == 0) {
return Collections.emptyList();
}
return new IntArrayAsList(backingArray);
}
这一段做了入参校验之后 new 了一个 IntArrayAsList
@GwtCompatible
private static class IntArrayAsList extends AbstractList<Integer>
implements RandomAccess, Serializable {
final int[] array;
final int start;
final int end;
IntArrayAsList(int[] array) {
this(array, 0, array.length);
}
IntArrayAsList(int[] array, int start, int end) {
this.array = array; //仅仅是对之前数组的引用,并没有新建内存空间
this.start = start;
this.end = end;
}
}
主要关注其构造方法,发现他并没有出现分配内存生成一个List<>而仅仅是对之前数组的引用.对原数组的修改会映射到新List<>中.
猜测这样做的考虑是生成一个只读的数组方便一些读取的操作,因为不新建List<> 节省了内存空间.
5.Joinner & Splittrt
private static final Splitter SPLITTER = Splitter.onPattern("\\s{4}").limit(3).trimResults().omitEmptyStrings();
建议写成如上单例模式
Joiner.on("&").withKeyValueSeparator("=").join(map); //id=0&name=silence
第一个on的内容是加在不同的K-V之间,第二个on是加在一个K-V之间
.splitTolist() //return List<>
.omitEmptyStrings() // 去掉空值
.trimResults() //去掉其中的空格
.trimResults() 也可以传入一个 CharMatcher对象
.trimResults(CharMatcher.is("a")) // 过滤掉a
.trimResults(CharMatcher.anyOf("ab")) // 过滤掉a and b