Java常见关键词的区别

一、wait 和sleep的区别

sleep()睡眠时,保持对象锁,仍然占有该锁,而wait()睡眠时,释放对象锁。但是wait()和sleep()都可以通过interrupt()方法打断线程的暂停状态,从而使线程立刻抛出InterruptedException(但不建议使用该方法)

二、overload和overide的区别

Override在覆盖要注意 以下的几点:
  1. 覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
  2. 覆盖的方法的返回值必须和被覆盖的方法的返回值一致;
  3. 覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
  4. 被覆盖的方法不能为 private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。
Overload 可以翻译为重载,它是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM就会根据不同的参数样式,来选择合适的方法执行。在使用重载要注意以下的几点:
  1. 在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是 fun(int,float),但是不能为 fun(int,int));
  2. 不能通过访问权限、返回类型、抛出的异常进行重载;
  3. 方法的异常类型和数目不会对重载造成影响;
  4. 对于继承来说,如果某一方法在父类中是访问权限是 private,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。
重写 Overriding 是父类与子类之间多态性的一种表现,
重载 Overloading 是一个类中多态性的一种表现。很重要的一点就是,Overloaded 的方法是可以改变返回值的类型。

三、final,finally,finalize区别

final 用于声明属性,方法和类, 分别表示属性不可变, 方法不可覆盖, 类不可继承
finally 是异常处理语句结构的一部分,表示总是执行.
finalize 是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等. JVM不保证此方法总被调用.

四、error和exception的区别

Error类:一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢出等。如java.lang.StackOverFlowError和Java.lang.OutOfMemoryError。对于这类错误,Java编译器不去检查他们。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和预防,遇到这样的错误,建议让程序终止。
Exception类:表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常

Exception又分为运行时异常Runtime Exception和受检查的异常Checked Exception

RuntimeException:其特点是Java编译器不去检查它,也就是说,当程序中可能出现这类异常时,即使没有用try……catch捕获,也没有用throws抛出,还是会编译通过,如除数为零的ArithmeticException、错误的类型转换、数组越界访问和试图访问空指针等。
处理RuntimeException的原则是:如果出现RuntimeException,那么一定是程序员的错误。受检查的异常(IOException等):这类异常如果没有try……catch也没有throws抛出,编译是通不过的。这类异常一般是外部错误,例如文件找不到、试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。

五、HashTable,HashMap,concurrentHashMap,weakHashMap的区别

Java为数据结构中的映射定义了一个接口java.util.Map,它包括3个实现类:HashMap、HashTable和TreeMap

Map是用来存储键值对的数据结构,在数组中通过数组下标来对其内容索引的,而在Map中,则是通过对象来进行索引,用来索引的对象叫做key,其对应的对象叫做value。

HashMap是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。

由于HashMap和HashTable都采用了hash法进行索引,因此二者具有很多相似之处,它们主要有以下区别与联系:

1、HashMap是HashTable的轻量级实现(非线程安全的实现),它们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key)(但需要注意,最多只允许一条记录为null),而HashTable不允许。
2、HashMap把HashTable的contains方法去掉了,改成containsvalue和containsKey,因为contains方法容易让人引起误解。HashTable继承自Dictionary类,而HashTable是Java1.2引进的Map interface的一个实现。
3、HashTable的方法是线程安全的,而HashMap不支持线程的同步,所以不是线程安全的。在多个线程访问HashTable时,不需要开发人员对它进行同步,而对于HashMap,开发人员必须提供额外的同步机制。所以,就效率而言,HashMap可能高于HashTable。
4、HashTable使用Enumeration,HashMap使用Iterator。
5、HashTable和HashMap采用的hash/rehash算法都几乎一样,所以性能不会有很大的差异。
6、在HashTable中,hash数组默认大小是11,增加的方式是old x 2 + 1。在HashMap中hash数组的默认大小是16,而且一定是2的指数。
7、hash值的使用不同,HashTable直接使用对象的hashCode。

以上三种类型中,使用最多的是HashMap。HashMap里面存入的键值对在取出时没有固定的顺序,是随机的。一般而言,在Map中插入、删除和定位元素,HashMap是最好的选择。由于TreeMap实现了SortMap接口,能够把它保存的记录根据键排序,因此,取出来的是排序后的键值对,如果需要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。LinkedHashMap是HashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排序列。 WeakHashMap与HashMap类似,二者的不同之处在于WeakHashMap中key采用的是“弱引用”的方式,只要WeakHashMap中的key不再被外部引用,它就可以被垃圾回收器回收。而HashMap采用的是“强引用”的方式,当HashMap中的key没有被外部引用时,只有在这个key从HashMap中删除后,才可以被垃圾回收器回收。与OC中NSDictionary相同

六、弱引用&软引用的区别

| 引用类型 | 被垃圾回收时间 | ** 用途** | ** 生存时间** |
| 强引用 | 从来不会 | 对象的一般状态 | JVM停止运行时终止 |
| 软引用 | 在内存不足时 | 对象缓存 | 内存不足时终止 |
| 弱引用 | 在垃圾回收时 | 对象缓存 | gc运行后终止 |
| 虚引用 | Unknown | Unknown | Unknown |

七、i++是线程安全的吗

原子操作(atomic operation)是不需要synchronized,答案是否定的,i++和++i都不具有原子性。
i++:先赋值再自加。
++i:先自加再赋值。

i++和++i的线程安全分为两种情况:

1、如果i是局部变量(在方法里定义的),那么是线程安全的。因为局部变量是线程私有的,别的线程访问不到,其实也可以说没有线程安不安全之说,因为别的线程对他造不成影响。
2、如果i是全局变量,则同一进程的不同线程都可能访问到该变量,因而是线程不安全的,会产生脏读。看i的声明位置

八、抽象方法和虚方法的区别

虚方法必须有实现部分,抽象方法没有提供实现部分,抽象方法是一种强制派生类覆盖的方法,否则派生类将不能被实例化 类似OC 中categray 没有实现会编译报错
抽象方法只能在抽象类中声明,虚方法不是。其实如果类包含抽象方法,那么该类也是抽象的,也必须声明为抽象的。类似 OC中协议中定义的方法 ,必须声明协议 协议相当于抽象类

九、volatile关键词的作用

volatile也是变量修饰符,只能用来修饰变量。volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值

Java的内存机制

Java使用一个主内存来保存变量当前值,而每个线程则有其独立的工作内存。线程访问变量的时候会将变量的值拷贝到自己的工作内存中,这样,当线程对自己工作内存中的变量进行操作之后,就造成了工作内存中的变量拷贝的值与主内存中的变量值不同。

Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。而volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。

使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字

你可能感兴趣的:(JAVA,线程,JVM)