36.Integer a= 127,Integer b = 127;Integer c= 128,Integer d = 128;,相等吗?
答案是
a
和
b
相等,
c
和
d
不相等。
对于基本数据类型
= =
⽐较的值
对于引⽤数据类型
= =
⽐较的是地址
Integer a= 127
这种赋值,是⽤到了
Integer
⾃动装箱的机制。⾃动装箱的时候会去缓存池⾥取
Integer
对象,没有取到才会创建新的对象。
如果整型字⾯量的值在
-128
到
127
之间,那么⾃动装箱时不会
new
新的
Integer
对象,⽽是直接引⽤缓存池中的 Integer
对象,超过范围
a1==b1
的结果是
false
public static void main ( String [] args) {
Integer a = 127 ;
Integer b = 127 ;
Integer b 1 = new Integer( 127 ) ;
System . out . println ( a = = b ); //true
System . out . println ( b = = b 1 ); //false
Integer c = 128 ;
Integer d = 128 ;
System . out . println ( c = = d ); //false
}
什么是 Integer 缓存?
因为根据实践发现⼤部分的数据操作都集中在值⽐较⼩的范围,因此
Integer
搞了个缓存池,默认范围是 -128
到
127
,可以根据通过设置
JVM-XX:AutoBoxCacheMax=
来修改缓存的最⼤值,最⼩值改不了。
实现的原理是
int
在⾃动装箱的时候会调⽤
Integer.valueOf
,进⽽⽤到了
IntegerCache
。
很简单,就是判断下值是否在缓存范围之内,如果是的话去
IntegerCache
中取,不是的话就创建⼀个新的 Integer
对象。
IntegerCache
是⼀个静态内部类, 在静态块中会初始化好缓存值。
private static class IntegerCache {
… …
static {
/ /创 建Integer对象存 储
for ( int k = 0 ; k < cache . length ; k + + )
cache [ k ] = new Integer( j + + ) ;
… …
}
}
37.String 怎么转成 Integer 的?原理?
String
转成
Integer
,主要有两个⽅法:
- Integer.parseInt(String s)
- Integer.valueOf(String s)
不管哪⼀种,最终还是会调⽤
Integer
类内中的
parseInt(String s, int radix)
⽅法。
抛去⼀些边界之类的看看核⼼代码:
public static int parseInt( String s, int radix )
throws NumberFormatException
{
int result = 0 ;
/ /是 否 是 负 数
boolean negative = false ;
//char字符数组 下 标 和 长 度
int i = 0 , len = s. length ();
… …
int digit ;
/ /判 断 字符长度 是 否 ⼤ 于0, 否 则 抛 出 异 常
i f ( len > 0 ) {
… …
while ( i < len ) {
// Accumulating negatively avoids surprises near MAX_VALUE
/ /返 回 指 定 基 数中字符 表 ⽰ 的 数 值 。(此处是 ⼗ 进 制 数 值 )
digit = Character. digit(s. charAt ( i + + ) , radix ) ;
/ /进 制 位 乘 以 数 值
result * = radix ;
result - = digit ;
}
}
/ /根 据 上⾯得到的是 否 负 数 , 返回相应 的 值
return negative ? result : - result ;
}
去掉枝枝蔓蔓(当然这些枝枝蔓蔓可以去看看,源码
cover
了很多情况),其实剩下的就是⼀个简单的字符串遍历计算,不过计算⽅式有点反常规,是⽤负的值累减。
38.Object 类的常见⽅法?
Object
类是⼀个特殊的类,是所有类的⽗类,也就是说所有类都可以调⽤它的⽅法。它主要提供了以下 11
个⽅法,⼤概可以分为六类:
- 对象⽐较:
- public native int hashCode() :native ⽅法,⽤于返回对象的哈希码,主要使⽤在哈希表中, ⽐如 JDK 中的 HashMap。
- public boolean equals(Object obj):⽤于⽐较 2 个对象的内存地址是否相等,String 类对该⽅法进⾏了重写⽤户⽐较字符串的值是否相等。
- 对象拷贝:
- protected native Object clone() throws CloneNotSupportedException:naitive ⽅法,⽤于 创建并返回当前对象的⼀份拷贝。⼀般情况下,对于任何对象 x,表达式 x.clone() != x 为 true,x.clone().getClass() == x.getClass() 为 true。Object 本⾝没有实现 Cloneable 接口, 所以不重写 clone ⽅法并且进⾏调⽤的话会发⽣ CloneNotSupportedException 异常。
- 对象转字符串:
- public String toString():返回类的名字@实例的哈希码的 16 进制的字符串。建议 Object 所有的⼦类都重写这个⽅法。
- 多线程调度:
- public final native void notify():native ⽅法,并且不能重写。唤醒⼀个在此对象监视器上等 待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒⼀个。
- public final native void notifyAll():native ⽅法,并且不能重写。跟 notify ⼀样,唯⼀的区别就是会唤醒在此对象监视器上等待的所有线程,⽽不是⼀个线程。
- public final native void wait(long timeout) throws InterruptedException:native ⽅法,并 且不能重写。暂停线程的执⾏。注意:sleep ⽅法没有释放锁,⽽ wait ⽅法释放了锁 。timeout 是等待时间。
- public final void wait(long timeout, int nanos) throws InterruptedException:多了 nanos 参数,这个参数表⽰额外时间(以毫微秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 毫秒。
- public final void wait() throws InterruptedException:跟之前的 2 个 wait ⽅法⼀样,只不 过该⽅法⼀直等待,没有超时时间这个概念
- 反射:
- public final native Class<?> getClass():native ⽅法,⽤于返回当前运⾏时对象的 Class 对 象,使⽤了 final 关键字修饰,故不允许⼦类重写。
- 垃圾回收:
- protected void finalize() throws Throwable :通知垃圾收集器回收对象。