J2SE基础面试题


1、九种基本数据类型的大小,以及他们的封装类。

java提供了一组基本数据类型,包括

boolean, byte, char, short,  int, long, float, double, void.

同时,java也提供了这些类型的封装类,分别为

Boolean, Byte, Character, Short, Integer, Long, Float, Double, Void

2、Switch能否用string做参数

在Java5以前,switch(expr)中,exper只能是byte,short,char,int类型。

从Java5开始,java中引入了枚举类型,即enum类型。

从Java7开始,exper还可以是String类型。

但是long在所有版本中都是不可以的。

3、equals与==的区别

通俗点讲:==是看看左右是不是一个东西。equals是看看左右是不是长得一样。

术语来讲的区别:

1.==是判断两个变量或实例是不是指向同一个内存空间

equals是判断两个变量或实例所指向的内存空间的值是不是相同

2.==是指对内存地址进行比较

equals()是对字符串的内容进行比较

3.==指引用是否相同

equals()指的是值是否相同

4、Object有哪些共用的方法

Object是所有类的父类,任何类都默认继承Object。Object类到底实现了哪些方法?

1.clone方法

保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。

主要是JAVA里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递,我们有时候不希望在方法里讲参数改变,这是就需要在类中复写clone方法。

2.getClass方法

final方法,获得运行时类型。

3.toString方法

该方法用得比较多,一般子类都有覆盖。

4.finalize方法

该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。

5.equals方法

该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。

6.hashCode方法

该方法用于哈希查找,可以减少在查找中使用equals的次数,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。

一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash- Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。

如果不重写hashcode(),在HashSet中添加两个equals的对象,会将两个对象都加入进去。

7.wait方法

wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。

调用该方法后当前线程进入睡眠状态,直到以下事件发生。

(1)其他线程调用了该对象的notify方法。

(2)其他线程调用了该对象的notifyAll方法。

(3)其他线程调用了interrupt中断该线程。

(4)时间间隔到了。

此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。

8.notify方法

该方法唤醒在该对象上等待的某个线程。

9.notifyAll方法

该方法唤醒在该对象上等待的所有线程。

5、Java的四种引用,强弱软虚,用到的场景

强引用

最普遍的一种引用方式,如String s = "abc",变量s就是字符串“abc”的强引用,只要强引用存在,则垃圾回收器就不会回收这个对象。

软引用(SoftReference)

用于描述还有用但非必须的对象,如果内存足够,不回收,如果内存不足,则回收。一般用于实现内存敏感的高速缓存,软引用可以和引用队列ReferenceQueue联合使用,如果软引用的对象被垃圾回收,JVM就会把这个软引用加入到与之关联的引用队列中。

弱引用(WeakReference)

弱引用和软引用大致相同,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。

虚引用(PhantomReference)

就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。

虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

6、Hashcode的作用

hashCode()方法是Object类提供的,所以每个对象都有hashCode()方法,Object类的hashCode()方法默认是native的实现,可以认为不存在性能问题,因此不去仔细追究。

hashCode()方法主要用来配合散列集合的一些操作,比如计算索引。

在HashSet中判断对象是否存在集合中

1.调用obj.hashCode(),得到对应的hashcode值。

2.如果集合中没有存储这个hashcode对应的对象,则直接添加。如果集合中已经存储了这个hashcode对应的对象,则调用equals判断是否对象相同。

为了保证equals方法返回的结果和hashCode方法返回的结果一样,所以重写equals方法的同时也要重写hashCode方法。

HashMap的存取

HashMap是一个数组加链表组成的结构,链表里面的元素就是键值对。

HashMap的存放put方法

1.根据key的hashCode找到对应数组的位置。

2.然后遍历该位置上对应的链表,查找key是否已经存在。

3.如果key已经存在,则直接更新value,并将旧的value作为函数返回,如果key不存在,则通过头插法,将新的键值对放入当前链表的第一个位置。

HashMap的get方法

1.根据key的hashCode找到对应数组的位置。

2.然后遍历该位置上对应的链表,查找key是否已经存在。

7、ArrayList、LinkedList、Vector的区别

ArrayList 、LinkedList、Vector的区别

ArrayList、LinkedList、Vector都是实现了List接口

ArrayList本质上就是一个数组,当更多的元素添加到ArrayList中,其大小将会动态的进行增长,内部元素可以通过get与set方法进行访问。

elementDataObject类型的数组transient Object[] elementData;,保存添加到ArrayList中的数据。初始默认容量为initialCapacity,默认为DEFAULT_CAPACITY,容量为10 。size为ArrayList真正的容量,get和set操作时都会通过rangeCheck(int index)方法对index进行判断,然后如果越界的话就会报出我们常见的IndexOutOfBoundsException异常。

LinkedList是一个双链表,因此在删除和添加元素的时候便优于数组形式的ArrayList,但是在get与set方面弱于ArrayList.

getFirst();

getLast();

获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException

removeFirst();

removeLast();

获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException

peekFirst();

peekLast();

获取元素,但不删除元素。如果集合中没有元素,会返回null。

pollFirst();

pollLast();

获取元素,但是元素被删除。如果集合中没有元素,会返回null。

Vector几乎和ArrayList相同,但是Vector是线程安全的。Vector和ArrayList在更多元素添加进来时会请求更大的空间。Vector每次请求其大小的双倍空间,而ArrayList每次对size增长50%。

8、String、StringBuffer与StringBuilder的区别

String 字符串常量

StringBuffer 字符串变量(线程安全)

StringBuilder 字符串变量(非线程安全)

1.String

就上述所言,String类是一个常量,是不可改变的对象,这也就是说每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将引用连接到新的对象

所以经常改变的字符串最好不要用String,因为每次改变值的时候就会创建一个新的对象,当旧的对象没有引用时,GC(垃圾收集器)就会回收这些旧对象,导致系统变慢

2.StringBuilder和StringBuffer

StringBuilder和StringBuffer都是处理字符串的类,他们的用法和方法几乎一致。

从字面上理解,这两个类是String的容器。一个是构造器,一个是缓冲区。

在对字符串操作时结果都会对 StringBuffer 或StringBuilder对象本身进行操作,而不是生成新的对象,再改变对象引用。

所以在字符串对象经常改变的情况下,我们推荐使用StringBuffer 或StringBuilder。

StringBuffer

Java.lang.StringBuffer:线程安全的可变字符序列。一个类似于 String 的字符串缓冲区。并且可以通过Api提供的方法改变内容和长度。

可将StringBuffer安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

StringBuilder

java.lang.StringBuilder:从 JDK 5 开始,为该类补充了一个单个线程使用的等价类,即 StringBuilder。

与StringBuffer 相比,通常应该优先用 StringBuilder类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。

在大部分情况下的优先级使用,StringBuilder>StringBuffer>String

StringBuffer的一些方法:

1.存储(主要方法)

将指定数据作为参数添加到已有数据结尾处。

StringBuffer append(char c);

StringBuffer append(CharSequence s);等一系列重载方法,可以参阅Api文档。

StringBuffer insert(int offset,数据):将指定数据作为参数添加到指定的index位置。

2.删除

StringBuffer delete(int start,int end):删除缓冲区中的数据,包含start,不包含end。

StringBuffer deleteCharAt(int index):删除指定位置的字符。

3.修改

StringBuffer replace(int start,int end,string str):将指定的位置范围替换成指定的数据。

void setCharAt(int index,char ch):将指定的位置替换成指定的数据。

4.反转

StringBuffer reverse():将容器里的数据反向输出。

当final用来修饰String和StringBuffer时的区别

要知道,当final用来修饰的时候,变量是不可变的,往细了说,是变量所连接的内存地址是不可变的。

因此,当String类被修饰时,此时的string就是一个常量,他的地址不可变,因此值不能改变;

但当用来修饰StringBuffer类时,却可以调用它的append方法,究其机理是StringBuffer类被创造可以改变他的内存地址,因此他的地址在每次调用append时都可以改变,这个变量也随之可变。

9、Map、Set、List、Queue、Stack的特点与用法。

Collection接口

Collection 有两个子接口 List 和 Set。

List有三个实现类:LinkedList、ArrayList、Vector。

ArrayList 是线程不安全的, Vector 是线程安全的,这两个类底层都是由数组实现的。

LinkedList 是非线程安全的,底层是由链表实现的。

Stack类:继承自Vector,实现一个后进先出的栈。提供了几个基本方法,push、pop、peek、empty、search等。

Set有两个实现类:HashSet、TreeSet,其中HashSet又包含LinkedHashMap。

List允许有重复值,可通过下标索引来取值。

Set不允许重复值,通过游标来取值。

对于List,关心的是顺序,它保证维护元素特定的顺序,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引来访问List中的元素。

对于Set,只关心某元素是否属于Set,而不关心它的顺序。

Map接口

Map接口有三个实现类:Hashtable、HashMap、TreeMap。

LinkedHashMap和WeakHashMap继承自HashMap,IdentifyHashMap继承自TreeMap。

对于Map,最大的特点是键值映射,且为一一映射,键不能重复,值可以,所以是用键来索引值。

HashTable是线程安全的,不能存储null值,HashMap不是线程安全的,可以存储null值,但最多允许一个key为null。

Queue接口:提供了几个基本方法,offer、poll、peek等。已知实现类有LinkedList、PriorityQueue等。

10、HashMap和HashTable的区别。

1 HashMap不是线程安全的

hastmap是一个接口 是map接口的子接口,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值。HashMap允许null key和null value,而hashtable不允许。

2 HashTable是线程安全的一个Collection。

HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。 HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。 HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。 Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。 最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差

11、HashMap和ConcurrentHashMap的区别,HashMap的底层源码。

12、TreeMap、HashMap、LindedHashMap的区别。

13、Collection包结构,与Collections的区别。

14、try catch finally,try里有return,finally还执行么?

15、Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况。

16、Java面向对象的三个特征与含义。

17、Override和Overload的含义去区别。

18、Interface与abstract类的区别。

19、Static class 与non static class的区别。

20、java多态的实现原理。

21、实现多线程的两种方法:Thread与Runable。

22、线程同步的方法:sychronized、lock、reentrantLock等。

23、锁的等级:方法锁、对象锁、类锁。

24、写出生产者消费者模式。

25、ThreadLocal的设计理念与作用。

26、ThreadPool用法与优势。

27、Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等。

28、wait()和sleep()的区别。

29、foreach与正常for循环效率对比。

30、Java IO与NIO。

31、反射的作用于原理。

32、泛型常用特点,List能否转为List。

33、解析XML的几种方式的原理与特点:DOM、SAX、PULL。

34、Java与C++对比。

35、Java1.7与1.8新特性。

36、设计模式:单例、工厂、适配器、责任链、观察者等等。

37、JNI的使用。


         

你可能感兴趣的:(J2SE基础面试题)