String s = new String(“xyz”);创建了1几个对象
两个,一个字符串对象,一个字符对象引用对象
Overload和Override的区别?Overloaded的方法是否可以改变返回值的类型?
方法的重写Overrideing和重载Overloading是Java多态性的不同表现。重写Overrideing是父类与子类之间多态性的一种表现,重载Overloing是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写Overrideing。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载Overloading。
Overloaded的方法是可以改变返回值的类型。
最常见的Runtime Exception
NullPointerException 空指针引用异常
ClassCastException 类型转换异常
IndexOutOfBoundsException 下标越界异常
NumberFormatException 数字格式异常
EOFException 文件已结束异常
FiileNotFoundException 文件未找到异常
NoSuchMethodException 方法未找到异常
error和exception有什么区别?
error表示恢复不是不可能但很困难的情况下的1一种严重问题,比如内存溢出,不可能指望程序能处理这样的情况;
exception表示一种设计或实现问题,也就是说,它表示如果程序运行正常,从不会发生的情况
String、StringBuffer和StringBuilder的区别?
String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,这样不仅效率低下,而且大量浪费有限的内存空间。
StringBuffer 和 StringBuilder 的值是长度可变的,并且不产生新的未使用对象。StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
String可以赋空值,后者不可以。
线程和进程的区别?
进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位。
简单介绍一下集合?
集合主要分为两大类:Collection和Map
Collection: ├List:有序可重复 ├ArrayList 底层数据结构:数组 查询快,增删慢 线程不安全,效率高 ├LinkedList 底层数据结构:链表 查询慢,增删快 线程不安全,效率高 ├Vector 底层数据结构:数组 查询快,增删慢 线程安全,效率低 ├Set:无序不可重复 ├HashSet 底层数据结构:哈希表 如何保证元素的唯一性呢? 依赖两个方法:hashCode()和equals(),自动生成即可 ├LinkedHashSet 底层数据结构:链表和哈希表 由链表保证元素有序 由哈希表保证元素唯一 ├TreeSet 底层数据结构:红黑树 Map: |-HashMap: 底层数据结构:键是哈希表结构,保证键的唯一性。可以存入null键,null值 线程不安全,效率高。 允许key或者value为null |-Hashtable: 底层数据结构:哈希表,不可以存入null键,null值 线程是安全,效率低。 |-TreeMap: 底层数据结构:二叉树,保证键的排序和唯一性。需要使用Comparable或者Comparator 进行比较排序 线程不安全,效率高。Hashmap线程不安全,怎么实现一个线程安全的HashMap?
我们知道HashMap底层的数据结构是数组+链表/红黑树,默认初始容量是16,当数组中的元素大于hashMap的初始容量乘以加载因子时(加载因子默认是0.75),HashMap就会进行扩容,容量变为原来的2倍,然后将原来的数据重新映射到新的桶里面,然后将原来的桶逐个置为null,使得引用失效。也就是在hashMap进行扩容的时候容易发生HashMap线程不安全。HashMap线程不安全主要会产生以下两种情况:1、在多线程的环境下,进行put()的时候会导致多线程的数据不一致。2、在多线程的环境下,对HashMap进行get操作可能因为扩容而引起死循环。
实现一个线程安全的HashMap
1、使用ConcurrentHashMap
2、使用Collections.synchonizedMap(Map<K,v> m)方法将HashMap变成一个线程安全的map。
线程的生命周期?
A:新生 new,每个线程都有自己的运行空间 B:就绪 start(),就绪不代表运行,代表线程具有可运行的能力,在就绪队列中排队等待cpu调度 C:运行 cpu把时间片分配给某个线程,这个线程就就行运行状态 D:阻塞 sleep()… E:死亡 执行完毕
start()方法和run()方法的区别?
只有调用start()方法,才会表现出多线程的特征,不同线程的run()方法里面的代码交替执行。如果只是调用run()方法,那么代码还是同步执行的,必须等待一个线程的run()方法里面的代码全部执行完毕之后,另外一个线程才可以执行其run()方法里面的代码。
java中的notify和notifyAll有什么区别?
这又是一个刁钻的问题,因为多线程可以等待单监控锁,Java API 的设计人员提供了一些方法当等待条件改变的时候通知它们,但是这些方法没有完全实现。notify()方法不能唤醒某个具体的线程,所以只有一个线程在等 待的时候它才有用武之地。而notifyAll()唤醒所有线程并允许他们争夺锁确保了至少有一个线程能继续运行。
什么是线程池?为什么要使用它?
创建线程花费昂贵的资源和时间,如果任务来了才创建那么响应时间会变长,而且一个进程能够创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。
如何避免死锁? 死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务,死锁的发生必须满足以下四个条件:
互斥条件:一个资源每次只能被一个进程使用。请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作来避免死锁。