Java程序员常规面试题1

来源:互联网 发布:sql的触发器 编辑:程序博客网 时间:2024/06/05 16:07
Java面试题
1、谈一谈“==”与“equals()”的区别
“==” 判断的是两个对象的内存地址是否一样,适用于原始数据类型(它们的变量存储的值是本身,而引用类型变量存储的是引用);
equals是Object类的方法,Object对它的实现比较内存地址,可以重写这个方法来自定义“相等”这个概念。比如类库中的String、Data等需要对这个方法进行重写。
综上,对于枚举类型和原始数据类型的相等性比较,应该使用“==”;对于引用类型的相等性比较,应该使用equals方法。

2、Java中的四种引用及其引用场景是什么?
强引用(StrongReference):通常使用new操作符创建一个对象时所返回的引用及为强应用。如果一个对象具有强引用,那垃圾回收期绝不会回收它。ps:我们平常用的A a = new A();就是强引用。
软引用(SoftReference):若一个对象只能通过弱引用到达,那么这个对象在内存不足时会被回收。若引用可用于图片缓存中,内存不足时,系统会自动回收不再使用的Bitmap。若引用也可以用来实现内存敏感的高速缓存。SoftReference<String> softRef=new SoftReference<String>(str);     // 软引用
弱引用(WeakErference): 若一个对象只能通过弱引用到达,那么它就会被回收(即使内存充足),同样也用于图片缓存中,这时候只要Bitmap不再使用就会被回收。只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。WeakReference<String> abcWeakRef = new WeakReference<String>(str);//弱引用
虚引用(PhantomReference):虚引用是Java中最“弱”的引用,通过它甚至无法获取被引用的对象,必须与引用队列连合使用。它存在的唯一作用就是当它指向的对象回收时,它本身会被加入到引用队列中,这样就可以知道它指向的对象何时被销毁了。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。
ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue); //虚引用

3、Object中定义了哪些方法?
clone(),equals(),hashCode(),toString(),notify(),notifyAll(),wait(),finalize(),getClass()。

4、ArrayList,LinkedList,Vector的区别是什么?
ArrayList:内部采用数组存储元素,支持高效随机访问,支持动态调整大小;
LinkedList:内部采用链表来存储元素,支持快速插入/删除元素,但不支持高效地随机访问;
Vector:可以看作县城安全版的ArrayList。

5、String、StringBuffer、StringBuilder的区别是什么?
String:不可变的字符序列,若要向其中添加新字符需要创建一个新的String对象;
StringBuilder:可变字符序列,支持向其中添加新字符(无需创建新对象);
StringBuffer:可以看作线程安全版的StringBuilder。

6、Map、Set、List、Queue、Stack的特点及用法。
Map<K,V>:Java中存储键值对的数据类型都实现了这个接口,表示“映射表”。支持的核心操作是get(Object key)以及put(K key,V value),分别用来回去键对应的值以及向映射表中插入键值对。
Set<E>:实现了这个接口的集合类型中不允许存在重复的元素,代表数学意义上的“集合”。它支持的核心操作是add(E e),remove(Object o),contains(Object o),分别用于添加元素,删除元素以及判定给定元素是否存在于集合中。
List<E>Java中集合框架中的列表类型都是先了这个接口,表示一种有序序列。支持get(int index),add(E e)等操作。
Queue(E):Java集合框架中的队列接口,代表了“先进先出”队列。支持add(E element),remove()等操作。
Stack<E>:Java集合框架中表示堆栈的数据类型,堆栈是一种"后进先出"的数据结构。支持push(E item),pop()等操作。

7、HashMap和HashTable的区别
HashMap是线程安全的,而HashTable不是;
HashMap中允许存在null键和null值,而HashTable不允许。
HashMap的底层实现是"基于拉链法的散列表"。

8、ConcurrentHashMap的实现原理
ConcurrentHashMap是支持并发读写的HashMap,它的特点是读取数据时无需加锁,写数据时可以保证加锁粒度尽可能的小。由于其内部采用“分段存储”,只需对要进行写操作的数据所在的“段”进行加锁。

9、TreeMap,LinkedHashMap,HashMap的区别
HashMap的底层实现是散列表,因此它内部存储的元素是无序的;
TreeMap的底层实现是红黑树,所以它内部的元素是有序的。排序的依据是自然序或者是创建TreeMap时所提供的比较器(Comparator)对象;
LinkedHashMap能够记住插入元素的顺序。

10、Conllection和Conllections的区别
Collection<E>是Java集合框架中的基本接口;
Collections是Jabalpur几个框架提供的一个工具类,其中包含了大量用于操作或返回集合的静态方法。

11、对于“try-catch-finally”,若try语句块中包含“return”语句,finally语句块会执行吗?
答案是会执行。只有两种情况finally块中的语句不会被执行:
  • 调用了System.exit()方法;
  • JVM“崩溃”了。

12、Java中的异常层次结构图
Java中的异常层次结构如下图所示:

我们可以看到Throwable类是异常层级中的基类。Error类表示内部错误,这类错误使我们无法控制的;Exception表示异常,RuntimeException及其子类属于未检查异常,这类异常包括ArrayIndexOutOfBoundsException、NullPointerException等,我们应该通过条件判断等方式语句避免未检查异常的发生。IOException及其子类属于已检查异常,编译器会检查我们是否为所有可能抛出的已检查异常提供了异常处理器,若没有则会报错。对于未检查异常,我们无需捕获(当然Java也允许我们捕获,但我们应该做的事避免未检查异常的发生)。

13、接口和抽象类的区别
接口是一种约定,实现接口的类要遵循这个约定;抽象类本质上是一个类,使用抽象类的代价要比接口大。接口与抽象类的对比如下:
  • 抽象类中可以包含属性,方法(包含抽象方法与有着具体实现的方法),常量;接口只能包含常量和方法声明。
  • 抽象类中的方法和成员变量可以定义可见性(比如public、private等);而接口中的方法只能为public(缺省为public)。
  • 一个子类只能有一个父类(具体类或抽象类);而一个接口可以继承一个多个接口,一个类也可以实现多个接口。
  • 子类中实现父类中的抽象方法时,可见性可以大于等于父类中的;而接口实现类中的接口 方法的可见性只能与接口中相同(public)。

14、 静态内部类与非静态内部类的区别
静态内部类不会持有外围类的引用,而非静态内部类会隐式持有外围类的一个引用。

15、Java中多态的实现原理
所谓多态,指的就是父类引用指向子类对象,调用方法时会调用子类的实现而不是父类的实现。多态的实现的关键在于“动态绑定”。

16、简述Java中进行线程同步的方法
  • volatile: Java Memory Model保证了对同一个volatile变量的写happens before对它的读;
  • synchronized: 可以来对一个代码块或是对一个方法上锁,被“锁住”的地方称为临界区,进入临界区的线程会获取对象的monitor,这样其他尝试进入临界区的线程会因无法获取monitor而被阻塞。由于等待另一个线程释放monitor而被阻塞的线程无法被中断。
  • ReentrantLock: 尝试获取锁的线程可以被中断并可以设置超时参数。
17、简述Java中具有哪几种粒度的锁
Java中可以对类、对象、方法或是代码块上锁。

18、给出“生产者-消费者”问题的一种解决方案
使用阻塞队列
public class BlockingQueueTest {    private int size = 20;    private ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(size);    public static void main(String[] args){        BlockingQueueTest test = new BlockingQueueTest();        Producer producer = test.new Producer();        Consumer consumer = test.new Consumer();        producer.start();        consumer.start();    }    class Consumer extends Thread{        @Override        public void run() {            while (true){                //从阻塞队列中取出一个元素                queue.take();                System.out.println("队列剩余"+queue.size()+"个元素");            }        }    }    class Producer extends Thread{        @Override        public void run() {            while (true){                //向组塞队列中插入一个元素                queue.put(1);                System.out.println("队列剩余空间:"+(size - queue.size()));            }        }    }}



19、ThreadLocal的设计理念作用
ThreadLocal的作用是提供线程内的局部变量,在多线程环境下访问时能保证各个线程内的ThreadLocal变量各自独立。也就是说,每个线程的ThreadLocal变量是自己专用的,其他线程是访问不到的。ThreadLocal最常用于以下这个场景:多线程环境下存在对非线程安全对象的并发访问,而且该对象不需要在线程间共享,但是我们不想加锁,这时候可以使用ThreadLocal来使得每个线程都持有一个该对象的副本。
原创粉丝点击