java面试系列--J2SE基础(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weisong530624687/article/details/79045405

从今天开始整理一个系列文章,忘了上次从哪里看到的这些问题,都是些常见的面试题,当时把问题记了下来,今天开始,一一解答学习,顺便提升自己的技术知识基础水平,如有不正确的地方,可提出来共勉,谢谢。

-----------------------------------------------------------------------------------------------------------------

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

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

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

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

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

2. Switch能否用string做参数?

jdk 7 之前,switch只能支持 byteshortcharint这几个基本数据类型和其对应的封装类型。switch后面的括号里面只能放int类型的值,但由于byteshortchar类型,它们会 自动 转换为int类型(精精度小的向大的转化),所以它们也支持。

注意,对于精度比int大的类型,比如longfloatdoulble,不会自动转换为int,如果想使用,就必须强转为int,如(int)float;

3. equals==的区别。

java中的数据类型,可分为两类:

1.基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean

  他们之间的比较,应用双等号(==,比较的是他们的值。

2.复合数据类型()

  当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为falseJAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。

  对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Objectequals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。

  public class TestString {

   public static void main(String[] args) {

  String s1 = "Monday";

  String s2 = "Monday";

  if (s1 == s2)

  {

  System.out.println("s1 == s2");}

  else{

  System.out.println("s1 != s2");}

 }

 }

编译并运行程序,输出:s1 == s2说明:s1s2引用同一个 String对象 -- "Monday"!

再稍微改动一下程序,会有更奇怪的发现:

public class TestString {

public static void main(String[] args) {

String s1 = "Monday";

String s2 = new String("Monday");

if (s1 == s2)

{System.out.println("s1 == s2");}

else

{System.out.println("s1 != s2");}

if (s1.equals(s2)) {System.out.println("s1 equals s2");}

else{

System.out.println("s1 not equals s2");}

}

}

我们将s2new操作符创建

程序输出:

s1 != s2

s1 equals s2

说明:s1 s2分别引用了两个"Monday"String对象

3) 字符串缓冲池

原来,程序在运行的时候会创建一个字符串缓冲池当使用 s2 = "Monday" 这样的表达是创建字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被放到了池中,所以在s2被创建的时候,程序找到了具有相同值的s1

s2引用s1所引用的对象"Monday"

第二段程序中,使用了 new 操作符,他明白的告诉程序:"我要一个新的!不要旧的!"于是一个新的"Monday"Sting对象被创建在内存中。他们的值相同,但是位置不同,一个在池中游泳一个在岸边休息。哎呀,真是资源浪费,明明是一样的非要分开做什么呢?

再次更改程序:

public class TestString {

public static void main(String[] args) {

String s1 = "Monday";

String s2 = new String("Monday");

s2 = s2.intern();

if (s1 == s2)

{System.out.println("s1 == s2");}

else

{System.out.println("s1 != s2");}

if (s1.equals(s2)) {System.out.println("s1 equals s2");}

else{

System.out.println("s1 not equals s2");}

}

}


这次加入:s2 = s2.intern();

程序输出:

s1 == s2

s1 equals s2

来,(java.lang.Stringintern()方法"abc".intern()方法的返回值还是字符串"abc",表面上看起来好像这个方 法没什么用处。但实际上,它做了个小动作:检查字符串池里是否存在"abc"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会 把"abc"添加到字符串池中,然后再返回它的引用。

4. Object有哪些公用方法?

clone/equals/finalize/toString/hashCode/getClass/wait/notify/notifyAll

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

强弱软虚。(1)宁肯oof,也不回收;(2oof之前回收;(3)不管是否oof都回收;(4)不影响对象生命周期,任何时候都会回收

6. Hashcode的作用。

为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSetHashMap以及HashTable

7. ArrayListLinkedListVector的区别。

ArrayListVector都是采用数组方式存储,可以直接根据下标查询,效率高,插入数据需要移动内存数据,效率慢,Vector又是采用synchronized,线程安全,性能相对ArrayList

LinkedList采用双向链表存储,按序索引和查找较慢,插入操作较快,

8. StringStringBufferStringBuilder的区别。

1).可变与不可变

String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。

private final char value[];

StringBuilderStringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的。

char[] value;

2).是否多线程安全

String中的对象是不可变的,也就可以理解为常量,显然线程安全。

AbstractStringBuilderStringBuilderStringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacityappendinsertindexOf等公共方法。

StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。看如下源码:

public synchronized StringBuffer reverse() {

    super.reverse();

    return this;

}

 

public int indexOf(String str) {

    return indexOf(str, 0);        //存在 public synchronized int indexOf(String str, int fromIndex) 方法

}

StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。

 3).StringBuilderStringBuffer共同点

StringBuilderStringBuffer有公共父类AbstractStringBuilder(抽象类)

  抽象类与接口的其中一个区别是:抽象类中可以定义一些子类的公共方法,子类只需要增加新的功能,不需要重复写已经存在的方法;而接口中只是对方法的申明和常量的定义。

StringBuilderStringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(...)。只是StringBuffer会在方法上加synchronized关键字,进行同步。

  最后,如果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer

猜你喜欢

转载自blog.csdn.net/weisong530624687/article/details/79045405