java,java基础面试笔试题


我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。
扫描二维码或搜索下图红色VX号,加VX好友,拉你进【程序员面试学习交流群】免费领取。也欢迎各位一起在群里探讨技术。
推荐文章:Java 面试知识点解析;Mysql优化技巧(数据库设计、命名规范、索引优化

 

1,进程和线程:线程是调度的基本单位 进程是资源分配的基本单位

 

2,线程基础



 

链接:https://www.nowcoder.com/questionTerminal/e33c72bceb4343879948342e2b6e3bca

来源:牛客网

狠狠地幸福

①继承Thread类(真正意义上的线程类),是Runnable接口的实现。

②实现Runnable接口,并重写里面的run方法。

③使用Executor框架创建线程池。Executor框架是juc里提供的线程池的实现。

调用线程的start():启动此线程;调用相应的run()方法

继承于Thread类的线程类,可以直接调用start方法启动线程(使用static也可以实现资源共享).一个线程(对象)只能够执行一次start(),而且不能通过Thread实现类对象的run()去启动一个线程。

实现Runnable接口的类需要再次用Thread类包装后才能调用start方法。(三个Thread对象包装一个类对象,就实现了资源共享)。

线程的使用的话,注意锁和同步的使用。(多线程访问共享资源容易出现线程安全问题)

 

一般情况下,常见的是第二种。

* Runnable接口有如下好处:

*①避免点继承的局限,一个类可以继承多个接口。

*②适合于资源的共享

 

/*

 * Thread的常用方法:

 * 1.start():启动线程并执行相应的run()方法

 * 2.run():子线程要执行的代码放入run()方法中

 * 3.currentThread():静态的,调取当前的线程

 * 4.getName():获取此线程的名字

 * 5.setName():设置此线程的名字

 * 6.yield():调用此方法的线程释放当前CPU的执行权(很可能自己再次抢到资源)

 * 7.join():在A线程中调用B线程的join()方法,表示:当执行到此方法,A线程停止执行,直至B线程执行完毕,

 * A线程再接着join()之后的代码执行

 * 8.isAlive():判断当前线程是否还存活

 * 9.sleep(long l):显式的让当前线程睡眠l毫秒  (只能捕获异常,因为父类run方法没有抛异常)

 * 10.线程通信(方法在Object类中):wait()   notify()  notifyAll()

 *

 *设置线程的优先级(非绝对,只是相对几率大些)

 * getPriority():返回线程优先值

 * setPriority(int newPriority):改变线程的优先级

 */





View Code

3,死锁



 

链接:https://www.nowcoder.com/questionTerminal/09b51b00891543d6b08ace80c0704b01

来源:牛客网

死锁 :是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去

 

(1) 因为系统资源不足。

(2) 进程运行推进顺序不合适。

(3) 资源分配不当等。

如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则

就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。

(1) 互斥条件:一个资源每次只能被一个进程使用。

(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之

一不满足,就不会发生死锁。

死锁的解除与预防:

理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和

解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确

定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态

的情况下占用资源。因此,对资源的分配要给予合理的规划。





View Code

4,集合类

java,java基础面试笔试题_第1张图片

java,java基础面试笔试题_第2张图片

5,多线程的iterator



 

链接:https://www.nowcoder.com/questionTerminal/95e4f9fa513c4ef5bd6344cc3819d3f7

来源:牛客网

一:快速失败(fail—fast)

          在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modification Exception。

          原理:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。

      注意:这里异常的抛出条件是检测到 modCount!=expectedmodCount 这个条件。如果集合发生变化时修改modCount值刚好又设置为了expectedmodCount值,则异常不会抛出。因此,不能依赖于这个异常是否抛出而进行并发操作的编程,这个异常只建议用于检测并发修改的bug。

      场景:java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改)。

    二:安全失败(fail—safe)

      采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。

      原理:由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发Concurrent Modification Exception。

      缺点:基于拷贝内容的优点是避免了Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。

          场景:java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。





View Code

6,hashmap



 

链接:https://www.nowcoder.com/questionTerminal/6bd3857199564b3fb2d3fee4f4de06ea

来源:牛客网

HashMap的底层是用hash数组和单向链表实现的 ,当调用put方法是,首先计算key的hashcode,定位到合适的数组索引,然后再在该索引上的单向链表进行循环遍历用equals比较key是否存在,如果存在则用新的value覆盖原值,如果没有则向后追加。HashMap的两个重要属性是容量capacity和加载因子loadfactor,默认值分布为16和0.75,当容器中的元素个数大于 capacity*loadfactor时,容器会进行扩容resize 为2n,在初始化Hashmap时可以对着两个值进行修改,负载因子0.75被证明为是性能比较好的取值,通常不会修改,那么只有初始容量capacity会导致频繁的扩容行为,这是非常耗费资源的操作,所以,如果事先能估算出容器所要存储的元素数量,最好在初始化时修改默认容量capacity,以防止频繁的resize操作影响性能。





View Code

7,hashtable



 

链接:https://www.nowcoder.com/questionTerminal/f93bce3b4f07467dbcaef98675a5d767

来源:牛客网

1、HashMap是非线程安全的,HashTable是线程安全的。

2、HashMap的键和值都允许有null值存在,而HashTable则不行。

3、因为线程安全的问题,HashMap效率比HashTable的要高。

4、Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线程环境。





View Code

8,Comparable和Comparator接口是



 

Collections.sort(listA);

链接:https://www.nowcoder.com/questionTerminal/99f7d1f4f8374e419a6d6924d35d9530

来源:牛客网

steaf

Comparable & Comparator 都是用来实现集合中元素的比较、排序的,只是 Comparable 是在集合内部定义的方法实现的排序,Comparator 是在集合外部实现的排序,所以,如想实现排序,就需要在集合外定义 Comparator 接口的方法或在集合内实现 Comparable 接口的方法。 Comparator位于包java.util下,而Comparable位于包 java.lang下 Comparable 是一个对象本身就已经支持自比较所需要实现的接口(如 String、Integer 自己就可以完成比较大小操作,已经实现了Comparable接口) 自定义的类要在加入list容器中后能够排序,可以实现Comparable接口,在用Collections类的sort方法排序时,如果不指定Comparator,那么就以自然顺序排序, 这里的自然顺序就是实现Comparable接口设定的排序方式。 而 Comparator 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。 可以说一个是自已完成比较,一个是外部程序实现比较的差别而已。 用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。 比如:你想对整数采用绝对值大小来排序,Integer 是不符合要求的,你不需要去修改 Integer 类(实际上你也不能这么做)去改变它的排序行为,只要使用一个实现了 Comparator 接口的对象来实现控制它的排序就行了。





View Code

9,ArrayList和LinkedList



 

ArrayList 是线性表(数组)

get() 直接读取第几个下标,复杂度 O(1)

add(E) 添加元素,直接在后面添加,复杂度O(1)

add(index, E) 添加元素,在第几个元素后面插入,后面的元素需要向后移动,复杂度O(n)

remove()删除元素,后面的元素需要逐个移动,复杂度O(n)

LinkedList 是链表的操作

get() 获取第几个元素,依次遍历,复杂度O(n)

add(E) 添加到末尾,复杂度O(1)

add(index, E) 添加第几个元素后,需要先查找到第几个元素,直接指针指向操作,复杂度O(n)

remove()删除元素,直接指针指向操作,复杂度O(1)





View Code

10,jvm堆的结构



 

链接:https://www.nowcoder.com/questionTerminal/5c3dc3914da548e5b0617f4da9da7488

来源:牛客网

虚拟机中的共划分为三个代:

        年轻代(Young Generation)、年老代(Old Generation)和持久代(Permanent 

Generation)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系

不大。年轻代和年老代的划分是对垃 圾收集影响比较大的。

年轻代:

        所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生

命周期短的对象。年轻代分三个区。一个Eden区,两个 Survivor区(一般而言)。大部分对象在

Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这

个 Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了

的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区

(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时

存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第

一个Survivor去过来的对象。而且,Survivor区总有一个是空的。同时,根据程序需要,

Survivor区是可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减

少被放到年老代的可能。

年老代:

        在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认

为年老代中存放的都是一些生命周期较长的对象。

持久代:

        用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应 

用可能动态生成或者调用一些class,例如Hibernate 等,在这种时候需要设置一个比较大的持 

久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=进行设置。





View Code

11,sendRedirect()和forward()



 

链接:https://www.nowcoder.com/questionTerminal/c6fba3939ff54a39985611b489a5fceb

来源:牛客网

forward是服务器内部的跳转,浏览器的地址栏不会发生变化,同时可以把request和response传递给后一个请求。sendRedirect()是浏览器方面的跳转,要发送两次请求,地址栏也会发生变化,同时request和response也会发生变化,重新生成新的对象。





View Code

 


转载:https://www.cnblogs.com/vhyc/p/9136610.html

推荐内容:
Java日志框架:logback详解
Java 开发岗面试知识点
一步步实现滑动验证码(拼图验证码),Java图片处理关键代码
分享1-3年经验的Java面试
详解Java的自动装箱与拆箱(Autoboxing and unboxing)
两年JAVA程序员的面试总结
Java实现OPC通信
用Maven实现一个protobuf的Java例子
Java对象的序列化和反序列化源码阅读
Java最常见的200+面试题及自己梳理的答案--面试必备(一)

 

你可能感兴趣的:(java)