1. 九种基本数据类型的大小,以及他们的封装类
| 数据类型 | 大小(字节) | 封装类型 | 默认值 | 取值范围 |
|---|---|---|---|---|
| byte | 1 | Byte | (byte)0 | [-2^7, -2^7-1] |
| short | 2 | Short | (short)0 | [-2^15, -2^15-1] |
| int | 4 | Integer | 0 | [-2^31, -2^31-1] |
| long | 8 | Long | 0L | [-2^63, -2^63-1] |
| float | 4 | Float | 0.0f | [-2^31, -2^31-1] |
| double | 8 | Double | 0.0d | [-2^63, -2^63-1] |
| boolean | - | Boolean | false | - |
| char | 2 | Character | \u0000(null) | |
| void | - | Void | - | - |
Java二进制数编码:
[原码]就是前面所介绍的二进制定点表示法,即最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小。
[反码]表示法规定:正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。
[补码]表示法规定:正数的补码与其原码相同;负数的补码是在其反码的末位加1。
Java 使 用 补 码 来 表 示 二 进 制 数 ,在 补码表示中 ,最高位为符号位 ,正 数的符号位为 0,负 数为 1。
最大的应该是0111 1111 即127
最小的应该是1000 0000 即-128(按位取反,然后对整数加1)
byte 是1个字节也就是8位负数的补码是该 数绝对值的原码按位取反 ,然 后对 整个数加 1
2. Switch 能否用 String 做参数?
Java 5 以前,Switch 只支持 byte、short、char、int 类型;
Java 5 开始,Switch 引入 enum 类型;
Java 7 开始,Switch 引入 String 类型。
3. equals 与 == 的区别?
equals 操作表示连个变量是否为同一个对象的引用,即比较堆内存中存放的地址;
== 操作对于基本数据类型比较的是他们的值,对于非基本数据类型比较的是变量在堆内存地址是否相同。
4. Object 有哪些公用方法?
| 公用方法 | 访问权限及修饰符 | 作用 |
|---|---|---|
| getClass | public/final/native | 获得运行时类型 |
| hashCode | public/native | 该方法用于哈希查找,可以减少在查找中使用 equals 的次数; 重写 equals 方法一般都要重写 hashCode; 在一些具有哈希功能的 Collection 中用到,在 HashSet 中如果不重写 hashCode 会将两个 equals 的对象都加入进去。 |
| equals | public | Object 中的 equal 和 == 的作用是一样的; String 等子类中的 equals 方法是比较值的,是因为 String 重写了 equals 方法。 |
| clone | public/native | 实现对象浅复制,只有在实现了 Cloneable 接口时才可以调用该方法 |
| toString | public | 将对象转为字符串 |
| notify | public/final/native | 该方法唤醒在该对象上等待的某个线程 |
| notifyAll | public/final/native | 该方法唤醒在该对象上等待的所有线程 |
| wait | public/final/native | 使当前线程等待该对象锁; 1.该方法必须在获取到该对象的同步锁后才能调用; 2.其它线程调用 notify 或是 wait 达到超时时间或者其它线程调用了 interrupt 中断了该线程,此时该线程就可以被调度了,如果是 interrupt 的则抛出异常; 3.调用对象的 wait 方法导致该线程阻塞; |
| finalize | public/final/native | 该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用 |
5. Java的四种引用(强软弱虚),用到的场景
| 引用类型 | 使用场景 | GC |
|---|---|---|
| 强引用 | String str = "hello" | 强引用指向的对象永远不会被 GC,及时抛出 OOM |
| 软引用(SoftReference) | SoftReference aSoftRef=new SoftReference(aRef); 可以用来实现内存敏感的高速缓存,防止内存泄露,增强程序健壮性 |
内存空间足够时不会被 GC,内存空间不足时就会回收这些对象 |
| 弱引用(WeakReference) | WeakReference<People>reference=new WeakReference<People>(new People("zhouqian",20)); |
当 JVM 进行垃圾回收时,无论内存是否充足都会回收被弱引用关联的对象 |
| 虚引用(PhantomReference) | ReferenceQueue<String> queue = new ReferenceQueue<String>(); PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue); 虚引用必须和引用队列关联使用 |
任何时候都可能被垃圾回收器回收 |
ReferenceQueue:
1.Reference queues, to which registered reference objects are appended by the garbage collector after the appropriate reachability changes are detected.
(Reference queues,在适当的时候检测到对象的可达性发生改变后,垃圾回收器就将已注册的引用对象添加到此队列中)
2.Reference 类首先把内存分为4种状态Active,Pending,Enqueued,Inactive
6. hashcode 方法的作用
hashcode 方法返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。
hashCode 的常规协定是:
1.在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。
从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。
2.当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
3.如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。
4.由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。为不相等的对象生成不同整数结果可以提高哈希表的性能。
7. ArrayList、LinkedList、Vector 的区别
| 类型 | 特点 |
|---|---|
| ArrayList | 是线程不安全的;是一个大小可变的数组;插入和移除元素代价高昂,因为插入和移除元素时需要移动既有的元素; |
| LinkedList | 是一个双向链表;插入和移除元素代价低廉;随机访问元素内容代价高昂; |
| Vector | 与 ArrayList 相似,但是是线程安全的;已经弃用; |
8. String、StringBuffer 与 StringBuilder 的区别
| 类型 | 特点 |
|---|---|
| String | 是字符串常量;String 对象一旦创建之后该对象是不可更改的; |
| StringBuffer | 是字符串变量;线程安全;适用于多线程下载字符缓冲区进行大量操作的情况; |
| StringBuilder | 是字符串变量;线程不安全;适用于单线程下载字符缓冲区进行大量操作的情况; |
常量池(onstant pool):
指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。
- String str = "abc" 和 String str1 = new String("abc"):
1. String str1 = "abc";
System.out.println(str1 == "abc");
步骤:
1) 栈中开辟一块空间存放引用str1;
2) String池中开辟一块空间,存放String常量"abc";
3) 引用str1指向池中String常量"abc";
4) str1所指代的地址即常量"abc"所在地址,输出为true;
2. String str2 = new String("abc");
System.out.println(str2 == "abc");
步骤:
1) 栈中开辟一块空间存放引用str2;
2) 堆中开辟一块空间存放一个新建的String对象"abc";
3) 引用str2指向堆中的新建的String对象"abc";
4) str2所指代的对象地址为堆中地址,而常量"abc"地址在池中,输出为false;
3. String str3 = new String("abc");
System.out.println(str3 == str2);
步骤:
1) 栈中开辟一块空间存放引用str3;
2) 堆中开辟一块新空间存放另外一个(不同于str2所指)新建的String对象;
3) 引用str3指向另外新建的那个String对象 ;
4) str3和str2指向堆中不同的String对象,地址也不相同,输出为false;
4. String str4 = "a" + "b";
System.out.println(str4 == "ab");
步骤:
1) 栈中开辟一块空间存放引用str4;
2) 根据编译器合并已知量的优化功能,池中开辟一块空间,存放合并后的String常量"ab";
3) 引用str4指向池中常量"ab";
4) str4所指即池中常量"ab",输出为true;
5. final String s = "a"; //注意:这里s用final修饰,相当于一个常量
String str5 = s + "b";
System.out.println(str5 == "ab");
步骤:
同四
6. String s1 = "a";
String s2 = "b";
String str6 = s1 + s2;
System.out.println(str6 == "ab");
步骤:
1) 栈中开辟一块中间存放引用s1,s1指向池中String常量"a",
2) 栈中开辟一块中间存放引用s2,s2指向池中String常量"b",
3) 栈中开辟一块中间存放引用str5,
4) s1 + s2通过StringBuilder的最后一步toString()方法还原一个新的String对象"ab",因此堆中开辟一块空间存放此对象,
5) 引用str6指向堆中(s1 + s2)所还原的新String对象,
6) str6指向的对象在堆中,而常量"ab"在池中,输出为false
7. String str7 = "abc".substring(0, 2);
步骤:
1) 栈中开辟一块空间存放引用str7,
2) substring()方法还原一个新的String对象"ab"(不同于str6所指),堆中开辟一块空间存放此对象,
3) 引用str7指向堆中的新String对象,
8. String str8 = "abc".toUpperCase();
步骤:
1) 栈中开辟一块空间存放引用str6,
2) toUpperCase()方法还原一个新的String对象"ABC",池中并未开辟新的空间存放String常量"ABC",
3) 引用str8指向堆中的新String对象
9.String s="abc";
String s1=s;
System.out.println(s1=="abc");
s=s+"hello";
System.out.println(s1=="abc");
System.out.println(s=="abc");
步骤:
1)栈中开辟一块空间存放s;
2)Sting池中开辟一块空间用于存放"abc",栈中开辟一块空间存放变量s1;
3)系统输出true,在堆中开辟一块空间用于存放"abchello";
4)引用s指向堆中的"abchello";
5)系统输出true,然后输出false;
9. Map、Set、List、Queue、Stack 的特点与用法
| 类型 | 特点 | 用法 |
|---|---|---|
| Map | 键值对 | Map中可以将Key和Value单独抽取出来,其中KeySet()方法可以将所有的keys抽取成一个Set。而Values()方法可以将map中所有的values抽取成一个Set |
| Set | 不包含重复元素的集合 | - |
| List | 有序的可重复集合;涉及堆栈,队列等操作,建议使用List;快速插入和删除元素的,建议使用LinkedList;需要快速随机访问元素的,建议使用ArrayList | - |
| Queue | 遵从先进先出原则 | 使用时尽量避免add()和remove()方法,而是使用offer()来添加元素,使用poll()来移除元素,它的优点是可以通过返回值来判断是否成功 |
| Stack | 遵从后进先出原则 | 它提供了通常的push和pop操作,以及取堆栈顶点的peek()方法、测试堆栈是否为空的empty方法等 |