Java基础高频题

1.JDK和JRE有什么区别?

JDK:Java Development Kit的简称,java开发工具包,提供了Java的开发环境和运行环境

JRE:Java Runtime Environment的简称,java运行环境,为java的运行提供了所需环境

具体来说Jdk包含了JRE,同时还包含了编译java源码的编译器Javac,还包含了很多Java程序调试和分析工具。简单来说:如果你需要运行java程序,只需要安装JRE就可以了,如果你需要编写Java程序,需要安装JDK。

2.==和equals的区别是什么?

==对于基本类型来说是值比较,对于引用类型来说比较的是引用地址;

equals默认情况下是引用地址的比较,只是很多类重写了equals方法,比如String,Integer等把它变成了值比较。

3.重写(overwrite)和重载(overload)的区别?

重载:

发生在同一个类中

相同的方法名

参数列表不同

不看返回值

重写:

发生在子类与父类中

相同的方法名

相同的参数列表

返回值相同或者子类方法的返回值是父类方法返回值类型的子类

访问修饰符相同或者子类方法的修饰符范围大于父类

抛出的异常相同或者子类方法抛出的异常小于父类

4.两个对象的hashCode()相同,则equals()也一定为true,对吗?

不对。两个对象的hashCode()相同,equals()不一定true。

String"通话"和"重地"的hashCode()相同,然而equals()则为false,因为在散列表中,hashCode()相同相等的两个键值对的哈希值相等,然而哈希值相等并不一定能得出键值对相等。

5.final在java中有什么作用?

final修饰的类不能被继承

final修饰的方法不能被重写

final修饰的变量叫常量,常量必须初始化,初始化之后的值就不能被修改

6.java中的Math.round(-1.5)等于多少?

等于-1,算法应为:参数值+0.5的结果向下取整。

7.String属于基础的数据类型吗?

String不属于基础类型,基础类型有8种:byte、short、int、long、char、float、double、boolean,而String属于对象。

4大基本类型

整数:byte(1个字节),short(2个字节),int(4个字节),long(8个字节)

浮点数:float(4个字节),double(8个字节)

字符:char(2个字节)

布尔类型:boolean(1个字节)

8.String如何转换成基本数据类型?

一般用parse方法,例如:Integer.parseInt.

或者通过使用Apache lang NumberUtils工具类

9.Integer和int的区别?

1.Integer是int的包装类,int则是java的一种基本数据类型。

2.Integer变量必须实例化后才能使用,而int变量不需要。

3.Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值。

4.Integer的默认值是null,int的默认值是0

10.new Integer(1)和Integer a = 1有什么区别?

Integer a = 1;

Integer 变量指向的是java常量池中的对象。

new Integer(1);

new Integer()的变量指向堆中新建的对象。

两者在内存中的地址不同

11.Integer a = 128,b = 128;System.out.println(a==b)结果是false?为什么?

直接使用Integer包装类赋值,范围是在[-128,127]之间不会生成新的对象,查看Integer的源码可以看到调用的是Integer.ValueOf()方法,就相当于直接int赋值,直接把Java常量池中的对象拿来用,超过了范围就会申请在堆中new一个对象。

12.Java中操作字符串都有哪些类,它们之间有什么区别?

操作字符串的类有:String、StringBuffer、StringBuilder。

String和StringBuffer、StringBuilder的区别在于String声明的是不可变的对象,每次操作都会生成新的String对象,然后将指针指向新的String对象,而StringBuffer、StringBuilder可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用String。

StringBuffer和StringBuilder最大区别在于,StringBuffer是线程安全的,而StringBuilder是非线程安全的,但StringBuilder的性能却高于StringBuffer,所以在单线程环境下推荐使用StirngBuilder,多线程环境下推荐使用StringBuffer。

13.String str = "i"与String str = new String("i")一样吗?

不一样,因为内存的分配方式不一样。String str = "i"的方式,Java虚拟机会将其分配到常量池中;而String str = new String("i")则会被分配到堆内存中。

14.如何将字符串反转?

先把字符串转换成StringBuilder或者StringBuffer,然后再用reverse()方法即可。

15.String类的常用方法都有哪些?

indexOf();返回指定字符的索引

charAt();返回指定索引处的字符

replace();字符串替换

trim();去除字符串两端空白

split();分割字符串,返回一个分割后的字符串数组

getBytes();返回字符串的byte类型数组

length();返回字符串长度

toLowerCase();将字符串转换成小写字母

toUpperCase();将字符串转换成大写字符

subStirng();截取字符串

equals();字符串比较

16.抽象类必须有抽象方法吗?

不需要,抽象类不一定非要有抽象方法。(但是包含一个抽象方法的类一定是抽象类)

17.普通类和抽象类有哪些区别?

普通类不能包含抽象方法,抽象类可以包含抽象方法

抽象类不能直接实例化,普通类可以直接实例化

18.抽象类能使用final修饰吗?

不能。定义抽象类就是让其他类继承的,如果定义为final该类就不能被继承,这样彼此就会产生那矛盾,所以final不能修饰抽象类

19.接口和抽象类有什么区别?

默认方法实现:抽象类可以有默认方法实现;接口不能有默认的方法实现。

实现:抽象类的子类使用extends来继承;接口必须使用implements来实现接口。

构造函数:抽象类可以有构造函数;接口不能。

实现数量:类可以实现很多接口;但只能继承一个抽象类。

访问修饰符:接口中的方法默认使用public修饰;抽象类中的方法可以是任意访问修饰符。

20.&和&&有什么区别?

&和&&都可以用作逻辑"与"的运算符,表示逻辑"与"(and),当运算符两边的表达式结果都为true时,整个运算结果才为true,否则只要有一方为false,则结果为false。

&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式。&即不管第一个表达式为false还是true,第二个表达式都会参与运算。

&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如,0x31 & 0x0f的结果为0x01。

21.Java中Io流分为几种?

按功能来分:输入流(input)、输出流(output)

按类型来分:字节流、字符流

22.字节流和字符流的区别是?

基本单位:字节流操作的基本单元是字节;字符流操作的基本单元是Unicode码元。

缓冲区:字节流默认不适用缓冲区;字符流使用。

处理类型:字节流通常用于处理二进制数据,实际上它可以处理任意类型的数据,但它不支持直接写入或者读取Unicode码元;字符流通常处理文本数据,它支持写入以及读取Unicode码元。

23.BIO,NIO,AIO有什么区别?

BIO:Block IO 同步阻塞式IO,就是我们平常使用的传统IO,它的特点是模式简单使用方便,并发处理能力低。

NIO:New IO同步非阻塞IO,是传统IO的升级,客户端和服务器端通过Channel(通道)通讯,实现了多路复用。

AIO:Asynchronous IO是NIO的升级,也叫NIO2,实现了异步非阻塞IO,异步IO的操作基于时间和回调机制。

24.Files的常用方法都有哪些?

Files.exists();检测文件路径是否存在

Files.createFile();创建文件

Files.createDirectory();创建文件夹

Files.delete();删除一个文件或目录

Files.copy();复制文件

Files.move();移动文件

Files.size();查看文件个数

Files.read();读取文件

Files.write();写入文件

25.常用的数据结构?

一.线性表

1.数组实现

2.链表

二.栈与队列

三.树与二叉树

1.树

2.二叉树基本概念

3.二叉查找树

4.平衡二叉树

5.红黑树

26.Java容器都有哪些?

Java容器分为Collection和Map两大类,其下又有很多子类,如下:

Collection:

List、ArrayList、LinkedList、Vextor、Stack

Set、HashSet、LinkedHashSet、TreeSet

Map:

HashMap、LinkedHashMap、TreeMap、Hashtable

27.Collection和Collections有什么区别?

Collection是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如List、Set等。

Collections是一个包装类,包含了很多静态方法,不能被实例化,就像一个工具类,比如它提供的排序方法:Collections.sort(list)。排序、替换集合、翻转等。

28.List、Set、Map之间有什么区别?

Java中的集合包括三大类,它们是Set、List和Map,它们都处于Java.util包中,Set、List和Map都是接口,它们有各自的实现类。Set的实现类主要有HashSet和TreeSet,List的实现类主要有ArrayList,Map的实现类主要有HashMap和TreeMap。

Set中的对象不按特方式排序,并且没有重复对象。但它的有些实现类能对集合中的对象按特定方式排序,比如TreeSet类,它可以按照默认排序,也可以通过实现Java.util.Comparator<Type>接口来自定义排序方式。

List中的对象按照索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置检索对象,如通过list.get(i)方式来获得List集合中的元素。

Map中的每一个元素包含一个键对象和值对象,它们成对出现,键对象不能重复,值对象可以重复。

29.HashMap和Hashtable有什么区别?

存储:HashMap允许key和value为null,而Hashtable不允许。

线程安全:HashMap是非线程安全的,Hashtable是线程安全的。

推荐:在Hashtable的类注释可以看到:Hashtable是保留类不建议使用,推荐在单线程环境下使用HashMap代替,如果需要多线程使用则用ConcurrentHashMap代替。

30.如何决定使用HashMap还是TreeMap?

对于在Map中插入、删除、定位一个元素这类操作,HashMap是最好的选择,因为相对而言HashMap的插入会更快,但如果你要对一个key集合进行有序的遍历,那TreeMap是更好的选择。

31.说一下HashMap的实现原理?

HashMap基于Hash算法实现的,我们通过put(key,value)存储,get(key)来获取。

当传入key时,HashMap会根据key,hashCode()计算出hash值,根据hash值将value保存在bucket(桶)里。

当计算出的hash值相同时,我们称之为hash冲突,HashMap的做法使用链表和红黑树存储相同的hash值的value。

java1.8对HashMap做了改进,在链表长度大于8的时候,将后面的数据存在红黑树中,以加快检索速度。后续如果由于删除或者其他原因调整了大小,当红黑树的节点小于或等于6个以后,又会恢复为链表形态。

32.具体说下,为什么1.8后hashMap要用链表+红黑树的组合呢?

这是一个时间和空间的问题。

红黑树时间快,占内存,是普通节点的二倍空间。

链表时间慢,节省内存。

因为数据小时,红黑树的速度也没有很明显,而且很占用空间,所以使用链表,但数据多时,需要使用红黑树来提高查询效率,所以就变成了红黑树。

33.自己实现一个HashMap?

HashMap的实现思路:

1.利用key的hashCode重新计算出当前对象在数组中的下标

2.存储时,如果出现hash值相同的key,此时有两种情况:

 (1)如果key相同,覆盖原始值(2)如果key不同(出现冲突),则将当前key-value放入链表中

3.获取值时,直接找到对应hash值对应的下标,再进行判断key是否相同,从而找到对应的value

34.说一下HashSet的实现原理?

HashSet实际上是一个HashMap实例,都是一个存放链表的数组。它不保证能够存储元素的迭代顺序;此类允许使用null元素。

HashSet中不允许有重复元素,这是因为HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap中的key上面,而value中的值都是统一的一个固定对象private static final Object PRESENT = new Object();

HashSet中add方法调用的是底层HashMap中的put()方法,而如果是在HashMap中调用put,首先会判断key是都存在,如果key存在则修改value值,如果key不存在则插入这个k-v。而在set中,因为value值没有用,也就不存在修改value值的说法,因此往HashSet中添加元素,首先判断元素(也就是key)是否存在,如果不存在则插入,如果存在则不插入,这样HashSet中就不存在重复值。

所以判断key是否存在就要重写元素的类equals()和hashCode()方法,当向Set中添加对象时,首先调用此对象所在类的hashCode()方法,计算此对象的哈希值,此哈希值决定了此对象在Set中存放的位置;若此位置没有被存储对象则直接存储,若已有对象则通过对象所在类的equals()比较两个对象是否相同,相同则不能添加。

35.ArrayList和LinkedList的区别是什么?

数据结构实现:ArrayList是动态数组的数据结构实现,而LinkedList是双向链表的数据结构实现。

随机访问效率:ArrayList比LinkedList在随机访问的时候效率要高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。

增加和删除效率:在非首尾的增加和删除操作,LinkedList要比ArrayList效率要高,因为ArrayList增删操作要影响数组内的其他数据的下标。

综合来说,在需要频繁读取集合中的元素时,更推荐使用ArrayList,而在插入和删除操作较多时,更推荐使用LinkedList。

36.如何实现数组和List之间的转换? 

数组转List:使用Arrays.asList(array)进行转换

List转数组:使用List自带的toArray()方法

37.ArrayList和Vetor的区别是什么?

线程安全:Vetor使用了Synchronized来实现线程同步,是线程安全的;而ArrayList是非线程安全的。

性能:ArrayList在性能方面要优于Vector。

扩容:ArrayList和Vector都会根据实际的需要动态的调整容量,只不过在Vector扩容每次都会增加一倍,而ArrayList只会增加0.5倍。

38.ArrayList什么时候会扩容?为什么要扩容自身的1.5倍?

ArrayList默认是null,当添加一个数据时,它的长度就会变成10,如果添加第11个时,就会去走它底层的一个grow()方法,使用位移运算来进行扩容,当前容量+(当前容量>>1)也就等于当前容量+(当前容量/2){>>1就是向右移动一位,相当于除以2}。

每次将扩容1.5倍,太大造成资源浪费;太小服务器频繁创建回收,导致服务器压力大。

39.Array和ArrayList有什么区别?

存储:Array可以存储基本数据类型和对象;而ArrayList只能存储对象。

长度:Array是指定固定大小的;而ArrayList大小是自动扩展的。

方法:Array没有那么多的内置方法;而ArrayList有比如:addAll、removeAll、iteration等方法。

40.在Queue中poll()和remove()有什么区别?

相同点:都是返回第一个元素,并在队列中删除返回的对象。

不同点:如果没有元素poll()会返回null;而remove()会直接抛出异常(NoSuchElementException)。

41.哪些集合类是线程安全的?

Vector、Hashtable、Stack都是线程安全的,而像HashMap则是非线程安全的,不过在JDK1.5之后随着Java.util.concurrent并发包的出现,它们也有了自定对应的线程安全类,比如HashMap对应的线程安全类就是ConcurrentHashMap。

42.迭代器Iterator是什么?

Iterator接口提供遍历任何Collection的接口。可以从一个Collection中使用迭代器方法来获取迭代器实例。迭代器取代了java集合框架中的Enumeration,迭代器允许调用者在迭代过程中移除元素。

在JDK1.2 以前还没有Iterator接口的时候,遍历集合需要使用Enumeration接口,它的用法和Iterator类似

43.Iterator怎么使用?有什么特点?

Iterator使用代码如下:

List<String> list = new ArrayList<String>();
Iterator<String> it = list.iterator();
while(it.hashNext()){
  String str = it.next();
}
 Map<Integer, String> map = new HashMap<>();
Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            System.out.println("one-----" + iterator.next() + "     ");
        }

Iterator的特点就是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出ConcurrentModificationException异常。

44.Iterator和ListIterator有什么区别?

Iterator可以遍历Set和List集合,而ListIterator只能遍历List。

Iterator只能单向遍历,而ListIterator可以双向遍历(向前/后遍历)。

ListIterator从Iterator接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。

45.怎么确保一个集合不能被修改?

可以使用Collections.unmodifiableCollection(Collection c)方法来创建一个只读集合,这样改变集合的任何操作都会抛出异常java.lang.UnsupportedOperationException异常。

46.手写排序算法、冒泡排序、插入排序、选择排序?

选择排序

public int[] xuanZe(int[] array){
    for(int i = 0; i < array.lenght; i++){
        for(int j = i+1; j < array.length; j++){
             if(arr[i] > arr[j]){
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
          }
      }   
   }
      return array;
}

冒泡排序

public int[] maoPao(int[] array){
   for(int i = 0; i < array.lenght; i++){
      for(int j = 0; j < array.length-1-i; j++){
          if(array[j]>array[j+1]){
            int temp = array[j];
            array[j] = array[j+1];
            array[j] = temp;
         }
      }  
   }
    return array;
}

插入排序

public int[] chaRu(int temp,int[] array){
   //默认第一个元素有序,从第二个元素开始循环比较
   for(int i = 1; i < array.length; i++){
      //当前元素依次与之前有序元素对比
      for(int j = i; j > 0; j--){
         if(array[j]>array[j+1]){
          temp = array[j];
          array[j] = array[j+1];
          array[j+1] = temp;
          }
       }
   }
     return array;
}

47.MD5算法是什么?

MD5信息摘要算法,一种被广泛使用的密码散列汉萨胡,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。

48.MD5算法能用来做什么?

1.密码

可以当作密码验证,为了保证密码不再cmd5网站上破译,最好加盐以及乱序,也可以支取一半md5的长度。md5是不可逆算法,只要保证算法不变,就能和数据库中的md5相匹配

2.搜索

以搜索为例,输入"abc 你好"和输入"你好 abc"的结果是不一样的,因为搜索时它们对应的md5是不一样的,可以根据这个md5去查询内容

3.版权

当一个视频或者音频创作出来时它的md5是唯一的,若以后有翻录等版本出来,即使画质,声音,文件名都一样,但是它们的md5验证是不一样的,所以也可以验证版权。比如用莫伊账户下载的视频它的账户信息也会和视频一起md5操作,如果以后这个人私自传播通过md5就可以去数据库中查找泄露版权的情况

4.文件完整性的校验

当下载一个文件时,服务器返回的信息中包括这个文件的md5,在本地下载完毕时进行md5,将这两个md5值进行比较,如果一致则说明文件完整没有丢包现象

5.文件上传

文件上传时会上传文件的信息此时将文件的md5上传,服务器中存储这个md5值,冰存储这个md5值所对应的已上传字节长度,比如未上传对应为0,已上传对应位-1,已上传200字节就对应200,这个上传的时候可以匹配到这个文件在服务器中的状态,方便做断点续传,只要源文件没有更改,即使更换个名字,换个账户都可以在服务器找到对应的文件,所以当服务器中已经有上传完毕的此文件时,别人再上传这个文件就可以实现妙传

49.并行和并发有什么区别?

并发:多个任务在同一CPU核上,按细分的时间片轮流执行

并行:多个处理器或多核处理器同时处理多个任务。

50.线程和进程的区别?

根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位。

在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看作轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的玉兴和程序计数器(PC),线程之间切换的开销小。

所处环境:在操作系统中能同时运行多个线程(程序),而在同一进程(程序中有多个线程同时执行(通过CPU)调度,在每个时间片中只有一个线程执行)

51.守护线程是什么?

守护线程是运行在后台的一种特殊进程。

它独立与控制终端并且周期性地执行某种任务或等待处理某些发生地事件,在Java中垃圾回收机制就是特殊地守护线程。

52.创建线程有哪几种方式?

三种。

继承Thread重写run方法;实现Runnable接口;实现Callable接口

  1. Callable 可以在任务结束的时候提供一个返回值,Runnable 无法提供这个功能
  2. Callable 的 call 方法分可以抛出异常,而 Runnable 的 run 方法不能抛出异常。

53.说一下Runnable和Callable有什么区别?

Java多线程有两个重要地接口,Runnable和Callable,分别提供一个run方法和call方法,二者差异较大。

1.Runnable提供run方法,无法通过throws抛出异常,所有CheckedException必须在run方法内部处理;Callable提供call方法,直接抛出Exception异常。

2.Runnable地run方法无返回值,Callable地call方法提供返回值用来表示任务运行的结果。

3.Runnable的可以作为Thread构造器的参数,通过开启新的线程来执行,也可以通过线程池来执行;而Callable只能通过线程池执行。

54.线程有哪些状态?

1.新建

新创建了一个线程对象。

2.等待

线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

3. 运行

等待状态的线程获得了CPU时间片,执行程序代码。

4. 阻塞

阻塞状态是指线程因为某种原因放弃了CPU 使用权,也即让出了CPU时间片,暂时停止运行。直到线程进入等待状态,才有机会再次获得CPU时间片 转到运行状态。

阻塞的情况分三种: 

等待阻塞运行的线程执行.wait()方法,JVM会把该线程放入等待队列中
同步阻塞运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
其他阻塞运行的线程执行Thread.sleep(l)或.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入等待状态。

5. 死亡

线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

55.sleep()和wait()有什么区别?

类的不同:sleep() 来自 Thread,wait() 来自 Object。

释放锁:sleep() 不释放锁;wait() 释放锁。

用法不同:sleep() 时间到会自动恢复;wait() 可以使用 notify()/notifyAll()直接唤醒。

56.notify()和notifyAll()有什么不同?

notifyAll()会唤醒所有的线程,notify()之后唤醒一个线程。

notifyAll() 调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。

而 notify()只会唤醒一个线程,具体唤醒哪一个线程由虚拟机控制。

57.线程的run()和start()有什么区别?

start()方法用于启动线程,run()方法用于执行线程的运行时代码。

run()可以重复调用,而start()只能调用一次。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值