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方法等 |