JAVA基础面试题

JAVA基础面试题

参考
(绝大部分参考上文,但是文章中有些问题答案不是十分合理,就进行了部分的修改)

1.集合类:List和Set比较,各自的子类的比较(ArrayList,Vector,LinkedList;HashSet,TreeSet)

List:元素是有序的,元素可以重复,因为每个元素有自己的角标(索引)
ArrayList:底层是数组结构,特点:查询快,增删稍慢,线程不同步;·A线程将元素放到索引0的位置,CPU调度线程A停止,B运行,也将元素放到索引0的位置,当A和B同时运行的时候Size就变成了2。
LinkedList:底层使用的是链表数据结构,特点是:增删很快,查询慢。线程不安全,线程安全问题是由多个线程同时读写一个资源造成的。
Vector:底层是数组,线程同步,Vector的方法前面加了synchronized关键字,被ArrayList代替了,现在用的只有他的枚举。

Set:元素是无序的,且不可以重复(存入和取出的顺序不一定一致),线程不同步。Set底层是使用Map实现的,故也可以通过ConcurrentHashMap的方式变通实现线程安全的Set.
HashSet:底层是Hash表。根据hashCode和equals方法来确定元素的唯一性。

Map:这个集合是存储键值对的,并且键是唯一的
HashTable:地城是哈希表数据结构,不能存储null键和null值,线程的同步的,效率比较低。现场安全,使用synchronized锁住整张Hash表实现线程安全。
HashMap:底层是哈希表,可以存入null键和null值,现场不同步,效率较高。
TreeMap:底层是二叉树,线程不同步,可以用于对map集合的键进行排序。
ConcurrentHashMap:现场安全,允许多个修改操作并发进行,其关键在于使用了锁分离技术,他使用了多个锁来控制hash表的不同部分进行修改。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的Hashtable,他们有自己的锁。只要多个修改发生在不同的段上就可以并发进行。
TreeSet:可以对Set集合中的元素进行排序(自然顺序),底层是二叉树。

2.HashMap的底层实现,ConcurrentHashMap的底层实现

HashMap实际上是一个“链表散列",即数组和链表的结合体。允许null键和null值。
HashMap底层就是一个数据结构,数组中每一项又是一个链表。当新建一个HashMap的时候就会初始化一个数组。
HashMap是基于hash算法实现的。通过put(key,value)存储对象到HashMap中,通过get(key)获取对象。当使用put的时候,先根据key的hashCode()值进行hash计算,根据hash的值得到这个元素在数组中的位置,将元素存储在该位置的链表上。当使用get的时候,首先HashMap会对key的hasCode()的值进行hash计算,根据hash值找到这个元素在数组中的位置,将元素从该位置的链表中取出。
当多线程的情况下,可能会产生条件竞争。当重新调整HashMap大小的时候,确实存在条件竞争,如果两个线程都发现HashMap需要重新调整大小的时候,他们会同时试着调整大小,在调整的过程中,存储在链表中的元素的次序会反过来,因为移动到新的数组位置的时候,HashMap并不会将元素放到LinkList的尾部,而是放到头部,这是为了避免尾部遍历(tail traversing)。如果条件竞争发生了,那就就死循环了。

ConcurrentHashMap基于双数组的链表的Map接口同步实现
ConcurrentHashMap中不允许使用null值和null键。
ConcurrentHashMap是无序的。

为什么使用ConcurrentHashMap:
HashMap是非线程安全的,当我们只有一个线程的时候不会有问题,如果我们涉及到多线程读写的时候,HashMap就会fail-fast。要解决HashMap同步的问题,解决方案有:Hashtable、Collections.synchronizedMap(hashMap)这两种方式都是对整个hash表结构上加上同步锁,性能不高,所以我们可以使用ConcurrentHashMap,既能同步又能多线程访问。
ConcurrentHashMap的数据结构:数据结构为一个Segment的数组,Segment的数据结构为HashEntry的数组,而HashEntry存的使我们的键值对,可以构成链表。

3. 如何实现HashMap的顺序存储

可以参考LinkedHashMap底层实现LinkedHashMap底层使用哈希表与双向链表来保存所有的元素,他维护这一个运行于所有条目的双向链表,此链表定义了迭代顺序,这个迭代顺序可以是插入顺序或者是访问顺序。
1.按插入顺序的链表:在LinkedHashMap调用get方法后,输出的顺序和输入时相同,这样是按插入顺序的链表,默认是按插入顺序排序。
2.按访问顺序链表:在LinkedHashMap调用get方法后,会将这次访问的元素移动到链表尾部,不断分为可以形成按访问顺序排序的链表。

4.String,StringBuffer和StringBuilder的区别

运行速度快慢:StringBuilder>StringBuffer>String
String慢的原因:String为字符串常量,而StringBuffer和StringBuilder均为字符串变量,即String对象一旦创建对象就是不可变更的,但是后两者可以修改。
String适用于少量字符串操作的情况,StringBuilder适用于单线程下字符串缓冲区进行大量操作的时候(线程不安全)。StringBuffer:适用于多线程下字符缓存区进行大量操作的情况(线程安全)

5.Object的方法有哪些:比如wait,为什么会有wait、notify、notifyAll

1.使用wait()、notify()、notifyAll()时需要首先对调用对象加锁
2.调用wait()方法后,线程状态会从RUNNING变为WAITING,并将当前线程加入到lock对象的等待队列中。
3.调用notify()和notifyAll()方法后,等待在lock对象的等待队列线程不会马上从wait()方法返回,必须要等到调用notifyAll()或notify()方法的线程将lock所释放,等待线程才有机会从等待队列返回。这里只是有机会,因为锁释放后,等待线程会出现竞争,只有竞争到该锁的线程才会从wait()方法返回,其他线程只能继续等待。
4.notify()方法将等待队列中所有线程移动到lock对象的同步队列,notifyAll()方法则会将等待队列所有线程移到对象的同步队列,被移动的线程的状态由WAITING变为BLOCKED
5.wait()方法上等待锁,可以通过wait(long timeout)设置等待超时时间。

6.wait和sleep的区别

sleep方法属于线程,wait方法属于对象
sleep休眠当前线程,并不会释放对象锁,wait使当前线程继续等待状态,释放对象所,只有针对此对象notify()方法(并且共享对象资源释放)后本线程才会继续执行。

7.JVM的内存机构,JVM的算法

JVM内存机构主要有三大块:堆内存、方法区和栈,几乎所有的对象实例都存放到堆里,如果堆中没有内存完成实例分配,并且堆也无法扩展的时候会抛出OutOfMemoryError异常。
每个方法被执行的时候都会同时穿件一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链表、方法出口等信息。
每一个方法被调用直至执行完成的过程,句对应这一个站扎在虚拟机栈中从入栈到出栈的过程。
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。

8.强引用、软引用和弱引用的区别

强引用:垃圾回收绝对不会回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMenoryError错误,使程序异常那时候终止,也不会随意 回收据欧强引用的对象来解决内存不足的问题。
软引用:如果内存空间足够,垃圾回收站就不会回收,如果内存空间不足就会回收。
弱引用:只具有弱引用的对象生命周期更加短暂。垃圾回收线程一旦发现只有弱引用的对象,不管内存是否足够都会回收。
总结:
强引用:String str = “abc”; list.add(str);
软引用:如果弱引用对象回收完之后,内存还是报警,继续回收软引用对象
弱引用:如果虚引用对象回收完之后,内存还是报警,继续回收弱引用对象
虚引用:虚拟机的内存不够使用,开始报警,这时候垃圾回收机制开始执行System.gc(); String s = “abc”;如果没有对象回收了, 就回收没虚引用的对象

9.数组在内存中的分配

对象在“new"的时候,会在堆上分配内存空间,然后返回对象的引用。数组也是一个对象。

10.举例设计模式

1.懒汉模式

public class SingletonDemo {
        private static SingletonDemo instance;
        private SingletonDemo(){}
        public static SingletonDemo getInstance(){
            if(instance==null){
                instance=new SingletonDemo();
            }
            return instance;
        }
    }

2.饿汉模式

public class SingletonDemo {
        private static SingletonDemo instance=new SingletonDemo();
        private SingletonDemo(){}
        public static SingletonDemo getInstance(){
            return instance;
        }
    }

3.简单工厂模式
面条工厂:

public abstract class INoodles {
        /**
         * 描述每种面条啥样的
         */
        public abstract void desc();
    }

兰州拉面(具体的产品类):

public class LzNoodles extends INoodles {
        @Override
        public void desc() {
            System.out.println("兰州拉面 上海的好贵 家里才5 6块钱一碗");
        }
    }

泡面(具体的产品类):

public class PaoNoodles extends INoodles {
        @Override
        public void desc() {
            System.out.println("泡面好吃 可不要贪杯");
        }
    }

“简单面馆”(简单工厂类),菜单如下:

public class SimpleNoodlesFactory {
        public static final int TYPE_LZ = 1;//兰州拉面
        public static final int TYPE_PM = 2;//泡面
        public static INoodles createNoodles(int type) {
            switch (type) {
                case TYPE_LZ:
                    return new LzNoodles();
                case TYPE_PM:
                    return new PaoNoodles();
                default:
                    return new PaoNoodles();
            }
        }
        /**
         * 简单工厂模式
         */
        void creat(){
            INoodles noodles = SimpleNoodlesFactory.createNoodles(SimpleNoodlesFactory.TYPE_PM);
                noodles.desc();
        }
    } 

11.springmvc的核心是什么,请求的流程是怎么处理的,控制反转怎么实现的

aop和ioc
流程:用户发送请求给服务器。url:user.do—>Dispatchservlet处理–>DispatchServlet通过HandleMapping调用这个url对应的Controller
Controller执行完毕后,如果返回字符串,则ViewResolver将字符串转化成相应的视图对象;如果返回ModelAndView对象,该对象本身就包含了视图对象信息。
DispatchServlet将执视图对象中的数据,输出给服务器并呈现给客户
IOC控制反转:典型的工厂模式,就是具有依赖注入功能的容器,是可以创建对象的容器,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
通常new一个实例,控制权由程序员控制,而"控制反转"是指new实例工作不由程序员来做而是交给Spring容器来做。。在Spring中BeanFactory是IOC容器的实际代表者
AOP依赖注入:典型的代理模式,面向切面编程将程序中的交叉业务逻辑(比如安全,日志,事务),封装成一个切面,然后注入到目标业务逻辑中去。
aop框架具有的两个特征: 1.各个步骤之间的良好隔离性 2.源代码无关性

12.mybatis如何处理结果集

反射、通过在mapper配置文件里配置的属性对照反射进对象里

13.java的多态表现在哪里

多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作
比如同一个打印机,可以打印黑白的纸张也可以打印彩色的,同样是人,却有黑人白人之分

14.接口的用途

接口定义一种规范,eg
1.接口就比如KFC,你一听KFC就知道是卖炸鸡薯条的,他可以有不同的分店,也可以有自己的创新食品(多态),但是招牌炸鸡、鸡肉卷、全家桶什么的肯定会有,
你不用进店看菜单就知道他有,但如果不叫KFC换成炸鸡店你也可以吃到炸鸡,但是你不进店看菜单你不知道他具体都卖的有哪些食品,这就是接口的好处
2.比如电插孔,多是两孔和三孔的那种,如果没有这种规范那每家电器公司都来做一种插孔的话,试想一下插头换了怎么办?是不是只能买原装的来替换了

15.http,https协议

http是一种超文本协议,默认端口80,以明文传输。
https基于HTTP协议,通过SSL或TLS提供加密处理数据、验证对方身份以及数据完整性保护(保证了数据在网络传输过程中的安全性)

16.osi五层网络协议

应用层、传输层、网络层、数据链路层、物理层
在这里插入图片描述
在这里插入图片描述

17.用过哪些加密算法

对称加密:加密解密密码一致(DES、3DES、AES…)
非对称加密算法:加密解密秘钥不一致(基于三个数学难题,大数分解[RSA],背包问题,双曲线[ECC,国产SM2]、结合PKI)
Hash算法类(摘要) Base64加密算法,SHA1加密算法、MD5加密算法

18.说说tcp三次握手,四次挥手

在这里插入图片描述
(1) 第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
(2) 第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。
(3) 第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据
在这里插入图片描述
(1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。
(2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
(3)服务器B关闭与客户端A的连接,发送一个FIN给客户端A。
(4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。

19.cookie和session的区别,分布式环境怎么保存用户状态

cookie存在客户端,session存在服务端
分布式Session的几种实现方式
1.基于数据库的Session共享
2.基于NFS共享文件系统
3.基于memcached 的session,如何保证 memcached 本身的高可用性?
4.基于resin/tomcat web容器本身的session复制机制
5.基于TT/Redis 或 jbosscache 进行 session 共享。
6.基于cookie 进行session共享(唯一值token)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值