1.九种基本数据类型的大小,以及它们的封装类
Java有九种基本数据类型,分别是:byte、short、int、long、char、float、double、boolean和void。
数据类型 | 大小 | 最小值 | 最大值 | 包装类型 |
---|---|---|---|---|
byte | 1个字节 | -2^7 | 2^7-1 | Byte |
short | 2个字节 | -2^15 | 2^15-1 | Short |
int | 4个字节 | -2^31 | 2^31-1 | Int |
long | 8个字节 | -2^63 | 2^63-1 | Long |
char | 2个字节 | Unicode 0 | Unicode 216 -1 | Character |
float | 4个字节 | IEEE754 | IEEE754 | Float |
double | 8个字节 | IEEE754 | IEEE754 | Double |
boolean | 未强制定义 | - | - | Boolean |
void | - | - | - | Void |
boolean
Java规范没有强制指定boolean类型变量所占用的空间,虽然boolean变量只需要1位即可保存,但是计算机在分配内存时一般最小单位是字节,所以boolean变量大部分时候实际占用8位。
类型转换
- 自动类型转换:从小类型到大类型可以自动完成。
byte->short->int->long->float->double
char->int - 强制类型转换:从大类型到小类型需要强制转换符,有可能会丢失精度。
Java基本类型大小与平台无关
Java基本类型占用的大小是按照占用的字节数个数来决定的,比如64位就是占用8个字节,因此能做到平台无关。
使用封装类的目的
在Java中使用基本类型来存储语言支持的基本数据类型,这里没有采用对象是考虑到性能因素。因为即使是最简单的数学计算,使用对象来处理也会有一些开销,但这对于数据计算没有必要。但是在Java中,集合类中存放的都是对象,为了使集合类也能够存放基本数据类型,Java提供了对应的包装类。
2.switch能否用string做参数?
在Java1.5之前只能用int类型,因为char、byte和short可以自动转换为int,所以也可以用,而float和double不能自动转换为int,所以不能直接作为参数。
在Java1.5后加入了枚举类型,在Java7后可以用String做参数。
3.equals和==的区别
equals比较的是对象是否相等,调用的是对象的equals方法,可以由开发者重写。而==判断的是地址是否相同。
4.object有哪些公用方法?
主要有wait()、notify()、notifyAll()、hashCode()、toString()、equals()、getClass()、clone()、finalize()9个方法。
4.1 wait()、notify()和notifyAll()
- wait()方法一直等待直到获得锁喝着被中断。
- notify()唤醒在该对象上等待的某个线程。
- notifyAll()唤醒在该对象上等待的所有线程。
在并发编程中,这三个方法针对的都是同一个对象。也就是说同一个object调用notify()或者totifyAll()唤醒的是同一个object中wait()的线程,而不是别的线程。wait()释放锁,sleep()不释放锁。
4.2 hashCode()和equals()
equals()用来判断两个对象是否相等,可重写。hashCode()用来计算哈希值确定存放地址。
当equals()方法被重写时需要重写hashCode()方法,因为相同的对象的hashCode也一定相等。但hashCode相等的两个对象却不一定相同。不然会导致存储数据的不唯一(存储了两个equals相等的数据)。
4.3 toString()
该方法用的较多,也比较简单,一般都有覆盖
4.4 clone()
实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法。clone()会在堆中分配一个区域,来存放该对象的备份,并建立一个新的引用指向该对象。即对象实例相等,引用不相等。
注意:clone()只是简单复制一个对象,如果该对象中还包括对其他对象的引用,那么clone()直接复制这个应用,即两个内存区域的引用指向同一个对象
4.5 finalize()
当垃圾回收器确定不存在对该对象的引用时,即对象处于可恢复状态时,由垃圾回收器调用此方法。有可能在调用finalize()后该对象又变成可达状态。该方法用于释放资源,何时被调用具有不确定性。开发者不应主动调用该方法,应交给垃圾回收器调用。
4.6 getClass()
final方法,获得运行时类型。
5. Java的四中引用,强弱软虚,用到的场景
- 强引用:new一个对象,并用一个引用变量指向它。强引用的对象处于可达状态,不可以被垃圾回收机制回收。
- 软引用:只有软引用的对象,在系统内存充足时,不会被系统回收,程序也可以使用该对象。当系统内存不足时,系统会回收它。软引用常用于内存敏感的程序中。
- 弱引用:与软引用相似,但是引用级别更低。不管系统内存空间是否充足,在系统进行垃圾回收时都会被回收。
- 虚引用:类似于完全没有引用,不能通过虚引用获得一个对象。主要用于跟踪对象被垃圾回收的状态,必须和引用队列配合使用。
应用场景:软引用和虚引用可以用于cache,因为cache不能保证绝对的可靠,因此可以用weakHashMap来当缓存,这样垃圾回收器可以自动进行回收。如果是重要的数据,则不能用weakHashMap。
6. hashCode的作用
用来配合基于散列的集合的,如HashMap,HashSet,hashTable之类的。用于计算散列值,确定存储的槽位。
- 为什么需要hashCode,有了equals不就可以了吗?
hashCode默认都是地址,即一个数值类型的数据,比较hashCode比比较对象是否相等要容易的多。而两个对象equals时其hashCode必定相同,当hashCode不同时两个对象必定不同。当插入一个新的对象到集合中时,先比较hashCode是否与集合中的任一对象相同,若不同则直接插入,不需要在进行equals比较,若hashCode相同在进行equals比较,这样可以大大降低复杂度,提高查找效率。
7. ArrayList、LinkedList、Vector的区别
- 数组实现。ArrayList和Vector底层采用数组的形式存储数据。因此查找的效率比较高,插入和删除效率比较低。而且Vector是线程安全的,在很多方法中都加了一个synchronized,将方法锁起来,因此效率比较低。(细节的话它们的扩容因子不一样大,ArrayList是1.5倍,Vector是2倍)。
- 链表实现。LinkedList采用双向链表实现,它继承了List和Queue两个接口,查找速度稍微低一些,但插入和删除效率高。同时由于继承了Queue,还可以当做队列来使用。
- 扩容问题。ArrayList和Vector使用数组实现,因此存在resize问题(扩容)。即重新计算数据大小,将原来的数据拷贝到新的数据中,因此比较耗时。而LinkedList采用链表形式,不存在resize问题,因此对于增长较快的应该采用LinkedList。
- 实现形式。set和list都继承了collection接口,但是list是有序的,一般采用数组或链表实现;而set是无序的,一般采用hash实现。
8.String、StringBuffer和StringBuilder的区别
- String类是不可变的。
- String类内部用final char[]实现。String不可变的关键是SUN公司的工程师在后面所有String的方法里很小心的没有动char[]里的元素。
- 同时String类是不可变的(final修饰String),每次操作都会返回一个新的数组对象。
- StringBuffer和StringBuilder是可变的。
- 它们的操作每一次都返回该字符串吧本身(return this)
- 都继承了AbstractStringBuilder,在AbstractStringBuilder中,char[]没有用final修饰。
- StringBuffer是线程安全的,StringBuilder是线程不安全的,也就是StringBuffer中很多方法中都加了synchronized对方法进行加锁,因此效率比较低。
- String对象在进行连接操作时,会用String字符串创建一个StringBuilder对象,在调用其append方法来连接两个字符串。因此在需要进行大量连接操作的时候,要使用StringBuilder或StringBuffer,节省资源消耗。
- 包装类Integer、Character之类的也是不可变的,它们像String一样,除了自身用final修饰,内部的int和char基本类型的变量也是用final修饰的。
9. Map、Set、List、Queue、Stack的特点与用法
- Map:以键值对形式存入数据,键可以为null。
- Set:继承collection接口,数据没有顺序,不能重复,可以存入null。Set是通过包装一个所有value都为null的Map实现的。
- Stack: 栈,继承了Vector类,因此Stack类是用数组实现的,且线程安全。
- Queue: 队列,LinkedList继承了Queue接口,可以用LinkedList创建队列。
10. HashMap和HashTable的区别
HashMap不是线程安全的,HashTable是线程安全的。HashMap允许key或value为null,HashTable不允许。同时HashTable继承Dictionary类,而hashMap,继承AbstractMap类,但是都实现Map接口。
住过HashMap要实现同步,可以用Collection.sychronbizedMap(HashMap),这样就能够达到HashTable的效果。