Java面试题(含推荐网课、文章、书籍)

以下无序列表是网上的资源,博客、视频连接。
上班可看
链表实战
https://www.jianshu.com/p/9a4561d42e9a
数组转二叉树
https://blog.csdn.net/qq_23858785/article/details/89196048
周瑜博客
https://www.yuque.com/renyong-jmovm/kb

计算机网络
http://c.biancheng.net/view/6391.html

算法
https://zhuanlan.zhihu.com/p/123416868

tomcat接受请求处理原理
https://blog.csdn.net/qq_22162093/article/details/106107779
https://www.cnblogs.com/lzb1096101803/p/4785246.html(重点-----)

synchronize加在不同地方的作用
https://blog.csdn.net/mulinsen77/article/details/88635558
https://blog.csdn.net/mulinsen77/article/details/84560429

给你100万条数据的一张表,你将如何查询优化?
cnblogs.com/llzhang123/p/9239682.html

ARP协议工作原理
https://www.cnblogs.com/csguo/p/7542944.html

线程池拒绝策略
https://www.cnblogs.com/yaowen/p/9336961.html

深入mysql架构总揽
https://www.cnblogs.com/annsshadow/p/5037667.html
手撕算法
链接: https://pan.baidu.com/s/1XPBm_rBXabih3JokDSPItw 密码: c6cs

1.string和stringbuilder和stringbuffer的区别
2. 动态代理
3. 四种引用类型
4. hashmap、hashtable、currenthashmap的区别
5. 面向对象的特征
6. 成员变量和局部变量
7. 自旋锁到底是什么东西,简书。
8. hashcode和equals
10.创建一个对象内存都做了哪些事情?
9. 说一下java内存管理机制
10. 什么是线程共享
11. 二进制的位运算
12. URL、URI和URN三者之间的区别
13. 一次完整的HTTP请求发生了什么?
14. hosts文件有哪些其他的作用?
15. 设计模式之饿汉、懒汉
16. hashmap怎么存储的?
17. jvm加载、连接、初始化 三者统称类加载或类初始化
18. 什么是字节码?好处是什么?
19. C++和java的不同有哪些?
20. 关于三次握手的面试题
21. http1.0和http1.1有何区别?
22. TIME_WAIT和CLOSE_WAIT的区别
23. TCP是怎么保证传输可靠的
24. 反射原理和获取class三种方式
25. 通过反射可以获取类里的各种属性、方法名…
26. Class.forName()和ClassLoader的区别
27. 垃圾回收算法
28. final关键字的作用
29. Java中访问修饰符public、private、protecte、default的意义
30. 什么是序列化?
31. 程序计数器
32. 运行时常量池和常量池的区别
33. 多线程里什么是上下文切换
34. 网络协议串连
35. spring事务回滚
36. https三次握手
37. 一加到一百简单写法
38. 获取select标签下选中的option的值和文本
39. JS实现跳转到页面指定ID位置
40. 为什么要分多层继承,不直接继承
41. post方式获取参数为何乱码
42. html弹出窗confirm样式
43. 获取input CheckBox里的被选中的value和text值
44. 在文本框按回车键执行换行,离开文本框按回车执行提交表单
45. 防止双击选中html中文字
46. modelmapper 两个list类型相互转换
47. ThreadLocal
48. volatile是如何保证可见性的
49. 为什么需要batch,批量插入数据库
50. 类中加上serialVersionUID的目的是什么
51. 数据库不使用外键的意义
52. 列转行 、行转列
53. mysql一条语句实现插入或更新的操作
54. spring添加事务失效
55. 事务的传播特性
56. ping 命令的作用和原理
57. cas
58. java泛型
59. 快慢指针的实际应用
60. Tomcat Server处理一个http请求的过程
61. 两种安全类型的单例模式

两种安全类型的单例模式

https://blog.csdn.net/weixin_43388450/article/details/105648637
public class Person {
    Person(){}
    private static class getPersonInstance{
         private static final Person person = new Person();
    }
    private Person getInstance(){
        return getPersonInstance.person;
    }
}

public enum  EnumSingleton {
    INSTANCE;
    public EnumSingleton getInstance(){
        return INSTANCE;
    }
}

完整的枚举类单例模式

public class User {
    //私有化构造函数
    private User(){ }
 
    //定义一个静态枚举类
    static enum SingletonEnum{
        //创建一个枚举对象,该对象天生为单例
        INSTANCE;
        private User user;
        //私有化枚举的构造函数
        private SingletonEnum(){
            user=new User();
        }
        public User getInstnce(){
            return user;
        }
    }
 
    //对外暴露一个获取User对象的静态方法
    public static User getInstance(){
        return SingletonEnum.INSTANCE.getInstnce();
    }
}

public class Test {
    public static void main(String [] args){
        System.out.println(User.getInstance());
        System.out.println(User.getInstance());
        System.out.println(User.getInstance()==User.getInstance());
    }
}
结果为true

Tomcat Server处理一个http请求的过程

Tomcat Server处理一个http请求的过程
https://blog.csdn.net/qq_16765615/article/details/79104308

假设来自客户的请求为:http://localhost:8080/wsota/wsota_index.jsp
1) 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得
2) Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应
3) Engine获得请求localhost/wsota/wsota_index.jsp,匹配它所拥有的所有虚拟主机Host
4) Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
5) localhost Host获得请求/wsota/wsota_index.jsp,匹配它所拥有的所有Context
6) Host匹配到路径为/wsota的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)
7) path="/wsota"的Context获得请求/wsota_index.jsp,在它的mapping table中寻找对应的servlet
8) Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类
9) 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
10)Context把执行完了之后的HttpServletResponse对象返回给Host
11)Host把HttpServletResponse对象返回给Engine
12)Engine把HttpServletResponse对象返回给Connector
13)Connector把HttpServletResponse对象返回给客户browser

快慢指针

https://blog.csdn.net/qq_21815981/article/details/79833976
https://www.jianshu.com/p/21b4b8d7d31b
https://zhuanlan.zhihu.com/p/112506218

java泛型

在Java中泛型起一定的约束作用,加了泛型他就是指一种类型数据的集合,他可以方便我们在编译阶段就可以发现
放错泛型的问题,加了泛型仅仅是一种规范,不是规定。比如我一个ArrayList<Integer>,他这个泛型规范放入
的元素是Integer类型,但是java有一个泛型擦除机制,他会在编译期把泛型去掉,此时如下:
final ArrayList<Integer> ints = new ArrayList<>();
final ArrayList<String> strs = new ArrayList<>();
System.out.println(ints.getClass() == strs.getClass()); ==> true

反射是在程序运行时动态改变程序,在编译期之后,也就是说在泛型擦除之后。变原始类型=>ArrayList<Object>
然后通过反射我就可以往里头放string...
final ArrayList<Integer> ints = new ArrayList<>();
final Method add = ints.getClass().getDeclaredMethod("add", Object.class);
add.invoke(ints, "aaa");

https://www.cnblogs.com/wuqinglong/p/9456193.html

cas

cas属于乐观锁也叫无锁,synchronized属于悲观锁,操作对象必须上锁。
synchronized:多个线程想要操作同一个资源时,必须获得锁才能对对象进行操作,当一个线程持有锁时,其他
线程就进入阻塞状态,进入内核态,(CPU是不会紧着一个线程执行,让其他线程饥饿,而是分配时间片,时间片执
行结束就让其他线程执行)当获取到锁时就会重新恢复到用户态,这一线程切换叫做上下文切换,是需要一定时间的。

而cas自旋锁是当一个线程获取到锁后,其他线程在没有获取到锁的情况会进入自旋状态,直到对象释放锁后,该
对象才退出自旋状态开始running。期间没有上下文切换从而加快了执行速度。
自旋锁在线程没有获取到锁的时候进入while循环,会占用CPU资源,若操作不当会造成CPU占用过高。
当少量线程等待锁会进入自旋状态,当等待的线程达到一定的数量是就会进行锁升级,变成重量级锁,等待的线程就
会进入阻塞队列。

ping 命令的作用和原理性

https://blog.csdn.net/lcx390549721/article/details/82781483

事务的传播特性

声明:A接口调用B接口,事务的有无均以A为参考,下面属性均加在B接口上。
http://blog.sina.com.cn/s/blog_787297830102wq8s.html
https://www.cnblogs.com/Chsy/p/12369357.html

1. REQUIRED: 事务默认采用REQUIRED,即若A无事务则B新建一个事务,若A有则B加入当前A事务。(AB同一个事务)
2. REQUIRED_NEW: 若A无事务,则B新建一个事务,若A有,则B新建一个隔离事务,与A无关,A执行到B时,A事务挂起,B事务(提交)执行完毕后A事务再接着执行。B发生异常则B回滚,异常被A捕获则A也回滚,未捕获则A正常执行。
3. NESTED: 若A无事务,则B新建一个事务,若A有,则B将嵌套进A事务,A提交B也提交,A回滚b也回滚。
4. SUPPORTS: 若A无事务,那么B就以非事务方式执行,若有就使用A事务。
5. NOT_SUPPROTED: 不支持事务(不支持但不会报错)
6. NEVER: 若无事务,就以非事务方式执行,有则抛出异常(必须不能有事务)
7. MANDATORY: 若没有则抛出异常,有则使用当前事务。(必须得有事务)

spring添加事务失效

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
在给接口通过加注解的形式添加事务时,可以在注解的属性里添加rollbackFor Exception,意在发生异常的
时候回滚事务,但是若在方法中把抛出的异常给捕获了,就不会执行回滚,事务失效。
解决事务失效的方法:
  1.catch中在抛出一个异常
  2.catch中手动进行回滚
https://www.cnblogs.com/bulrush/p/12166587.html

mysql一条语句实现插入或更新的操作

INSERT INTO TABLE (a,c) VALUES (1,3),(1,7) ON DUPLICATE KEY UPDATE c=VALUES(c);
或者
INSERT INTO table (id,a,b,c) select id,a,b,c from xxx ON DUPLICATE KEY UPDATE 
a=VALUES(a),b=VALUES(b),c=VALUES(c)

注意:ON DUPLICATE KEY UPDATE只是MySQL的特有语法,并不是SQL标准语法! 
这个语法和适合用在需要 判断记录是否存在,不存在则插入存在则更新的场景.

https://www.cnblogs.com/dongruiha/p/6780447.html

列转行 、行转列

sql server可以使用pivot关键字实现行转列,unpivot实现列转行。
https://www.jianshu.com/p/1c6fb0df9f58

mysql 可以使用case when 来实现。
https://www.cnblogs.com/mjbenkyo/p/7268242.html
https://www.jianshu.com/p/5a2dae144238

在这里插入图片描述

数据库不使用外键的意义

通过外键可以最大限度的保证数据的完整性。主表要删除数据,首先会查找副表是否有该条记录,若有则删除失败。
副表要添加数据,首先会查找主表是否有该条数据,若无则插入失败。

阿里巴巴规约强制要求不要使用外键关联,数据完整性在应用层去保证。
不使用外键的话,数据库管理简单,操作方便,性能高(导入导出等操作,insert,update,delete的时候更快)
方便根据业务维护。

https://blog.csdn.net/lixiaobo_203/article/details/81215139
eg.假若一个程序要insert上百万条数据,当外键存在时,每次操作数据库都要去扫描磁记录是否合法,
若不止一个外键存在时,这样的扫描数量是成级数的增长。一个小时做完的可能要用好几个小时。

类中加上serialVersionUID的目的是什么

具体的序列化过程是这样的:序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。

假若没有手动加serialVersionUID 
在我们写一个类后,系统会自动生成一个在字节码文件中,经过序列化从服务器传递到我们这儿,
假若这个类并未改变,则反序列化成功。但若在反序列化前此类被人为改变,则serialVersionUID 就会改变,
无法正确匹配serialVersionUID ,就会抛出invalidCastException。

若是手动在类中加上serialVersionUID =*****L
则在反序列化前改变类也会正常进行反序列化操作(比如删除源文件的一个字段)1、凡是被static修饰的字段是不会被序列化的
2、凡是被transient修饰符修饰的字段也是不会被序列化的

https://www.cnblogs.com/kabi/p/9139228.html
https://blog.csdn.net/u014750606/article/details/80040130
https://blog.csdn.net/java_mdzy/article/details/78354959

在这里插入图片描述

为什么需要batch,批量插入数据库

jdbc操作步骤
1.注册驱动
2.创建连接
3.获取执行SQL的preparestatement对象
4.获取SQL
5.执行execute
6.close

假若一百条数据需要插入数据库,在不使用batch的情况下,每条SQL执行都需要经过这六个步骤,
每条SQL执行都在一个事务里。频繁的连接断开,很是影响效率。

mysql 默认是autocommit=on也就是默认开启自动提交事务。这种情况下,一条sql就会开启一个事务,
这时候同时执行一万条update,就会导致实际开启一万个事务,然后挨个执行,挨个开启,挨个提交。

而使用batch的话,把一百条SQL语句通过addBatch,最后一块执行插入操作。
所有插入都在执行后才进行提交操作。
数据批量操作 
https://www.cnblogs.com/myseries/p/11191134.html
https://www.cnblogs.com/myseries/p/11191134.html
https://www.cnblogs.com/myseries/p/11191134.html
批量执行更新sql语句的优缺点分析:

情况一:mysql 默认是autocommit=on也就是默认开启自动提交事务。这种情况下,一条sql就会开启一个事务,这时候同时执行一万条update,就会导致实际开启一万个事务,然后挨个执行,挨个开启,挨个提交。

缺点:同时锁住数据较少,但是数据库资源占用严重,对外提供操作性能急剧下降。

情况二:当autocommit=off时,同时执行一万条update,那么只会开启一个事务,等到所有都update后,一并commit。

缺点:同时锁住数据较多,外面的select进不来,大量连接等待获取行锁,同样影响数据库对外服务能力。

 最终优化方案:

  建议,把autocommit设置off,然后执行update的时候,手动分批commit,分批条数限制100,或者200,
比如一万条update,按照每100条 就commit一次,10000个update总共需要100个事务,每次锁住100条数据。
性能将会得到很大提升。

分批次插入,分批次提交
若中间有异常需要回滚,则已提交的不会回滚,
还没执行的SQL(还没提交)会回滚。

volatile是如何保证可见性的

当一个共享变量被volatile修饰时,它会保证修改的值立即被更新到主内存。其他线程读取时会从内存中读到新值。
普通的共享变量不能保证可见性,其被写入内存的时机不确定。当其他线程去读,可能读到的是旧的值。
另外通过synchronized和lock也可以保证可见性。它们能保证同一时刻只有一个线程获取锁然后执行同步代码。
并在释放锁之前对变量的修改刷新到住内存中。以此来保证可见性

ThreadLocal

ThreadLocal和Synchronized都是为了解决多线程中相同变量的访问冲突问题,不同的点是

Synchronized是通过线程等待,牺牲时间来解决访问冲突
ThreadLocal是通过每个线程单独一份存储空间,牺牲空间来解决冲突,并且相比于Synchronized,
ThreadLocal具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问到想要的值。

modelmapper 两个list类型相互转换
3.自定义转换
在这里插入图片描述

防止双击选中html中文字
在这里插入图片描述

在文本框按回车键执行换行,离开文本框按回车执行提交表单

$(document).keydown(function(event){
     let target, tag;
     event = window.event;
     target = event.srcElement;
     code = event.keyCode;
     if (code == 13) {
         tag = target.tagName;
         if (tag != "TEXTAREA") {
             $('#myModal').modal("show");
         }
     }
 }); 
 ============================================================================
 参考下面这个
 =========================================================================
<script type="text/javascript">
 document.onkeydown = function(event) {  
	var target, code, tag;  
	if (!event) {  
		event = window.event; //针对ie浏览器                 
		target = event.srcElement;  
	   
		code = event.keyCode;  
		if (code == 13) {  
			tag = target.tagName;  
			if (tag != "INPUT") { return true; }  
			else { return false; }  
		}  
	}  
	else {  
		target = event.target; //针对遵循w3c标准的浏览器,如Firefox  
		code = event.keyCode;  
		if (code == 13) {  
			tag = target.tagName;  
			if (tag != "INPUT") { return false; }  
			else { return true; }   
		}  
	}  
}; 
</script>

获取input CheckBox里的被选中的value和text值

<input type="checkbox" name="rName" th:value="${role.roleId}" th:text="${role.roleName}">

	 var ids = [];
	 var rname = [];
	 $("input[name='rName']:checked").each(function(){
	     ids.push($(this).val());
	     rname.push($(this).parent().text())
	 })

html弹出窗confirm样式

data-toggle="modal" data-target="#myModal" 这两个必加在button上

<button type="button" class="col-1 btn btn-primary" data-toggle="modal" 
	data-target="#myModal" data-loading-text="登録" id="login">登録
</button>

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
                     aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title" id="cancelModalLabel">確認ダイアログ</h4>
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">×</span>
                </button>
        </div>
        <div class="modal-body">
            <form>
                <div class="form-group text-center">
                    <label class="control-label">問合せ情報を登録します。よろしいですか?</label>
               </div>
                   </form>
               </div>
               <div class="modal-footer">
                   <button type="button" class="btn btn-primary"
                           id="insertCutomerInfo">OK
                   </button>
                   <button type="button" class="btn btn-default" id="cancel" data-dismiss="modal">キャンセル
                  </button>
              </div>
          </div>
      </div>
  </div>

post方式获取参数为何乱码
在这里插入图片描述

为什么要分多层继承,不直接继承

 比如servlet,他的子类是httpservlet,我们要用servlet就得继承httpservlet,
 那为什么不直接继承servlet?
 因为比如说,servlet里面用五个接口方法分别对应着她的生命周期,init、service。。。
 				普通类实现接口就必须实现他的所有接口。
 但是我们用的时候只会用到service,其他四个是废物,与我们没关系,不然还得重写。
 所以整一个httpservlet,让他实现servlet的其余四个方法,留一个service接口供我们实现。
 而在service这里才是我们要写的业务逻辑。
 所以分层继承就是这个好处,不会整那么多没用的。
 
 实际是httpservlet要继承genericservlet抽象类,而genericservlet实现servlet接口。
 那么抽象类实现接口有什么意义?
			 https://www.zhihu.com/question/36909455
 抽象类当然能够实现接口,意义如下:一般来说我们使用普通类来实现接口,这个普通类就必须实现接口
 中所有的方法,这样的结果就是普通类中就需要实现多余的方法,造成代码冗余。但是如果我们使用的是
 抽象类来实现接口,那么就可以只实现接口中的部分方法,并且当其他类继承这个抽象类时,仍然可以实
 现接口中有但抽象类并未实现的方法。

JS实现跳转到页面指定ID位置

 window.location.hash = "#inqueryregisterform";
 $("#目标div块").animate({scrollTop:$("#跳转到的div块位置").offset().top},300毫秒);
 

获取select标签下选中的option的值和文本

<option value="值一">文本。。。<option>

$("#selectId").val()=====>value
$("#selectId").find("option:selected").text();======>选中option的文本

一加到一百简单写法

let arr1 =[1,2,3,4,5,6,7,8,9,10];
arr1.reduce((a,b)=>a+b);
550

https三次握手

第一次客户端发起请求获取 :
	1.服务器的数字签名证书 2.sayhello
第二次服务器响应回:
	1.数字签名证书 2.sayhello 3.生成对称加密密钥的算法要求
第三次客户端响应:(目的是交换AES-KEY)
	1.生成AES-KEY密钥 2.用服务器公钥加密对称密钥 3.可以发送信息了

spring事务回滚
一文带你看懂Spring事务!

编译期异常时不会导致事务回滚,运行期异常会。

网络协议串连

	http协议是应用层协议,是负责服务器与浏览器间的访问协议,本身是无状态的,所以需要有tcp协议进行可靠
传送。
	ip协议是网际层协议,其主要功能是寻址和分片,即是找到IP地址。本身不可靠,可能丢包。
	tcp协议属于传输层协议,负责发送数据包,经三次握手建立连接,为了传输方便,把数据分块编号发送,而ip
协议是搜索对方地址,一边中转一遍传送,丢包则重新发送,到达服务器按顺序重组。

在这里插入图片描述
多线程里什么是上下文切换

	多线程编程中一般线程的个数都大于 CPU 核心的个数,而一个 CPU 核心在任意时刻只能被一个线程使用,为
了让这些线程都能得到有效执行,CPU 采取的策略是为每个线程分配时间片并轮转的形式。当一个线程的时间片用完
的时候就会重新处于就绪状态让给其他线程使用并保留上一个任务的状态,这个过程就属于一次上下文切换。

线程间上下文切换的成本很高,因为发生线程切换前,需要保留上一个任务的状态,以便切回来的时候,可以再次加载这个任务的状态。如果线程数量庞大,会造成线程做上下文切换的时间甚至大于线程执行的时间,CPU负载变高。

运行时常量池和常量池的区别
https://blog.csdn.net/qq_26222859/article/details/73135660

	方法区里存储着class文件的信息和运行时常量池,class文件的信息包括类信息和class文件常量池。
	常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存
放。
	运行时常量池里的内容除了是class文件常量池里的内容外,还将class文件常量池里的符号引用转变为直接引
用,而且运行时常量池里的内容是能动态添加的。例如调用String的intern方法就能将string的值添加到String常
量池中,这里String常量池是包含在运行时常量池里的,但在jdk1.8后,将String常量池放到了堆中。

程序计数器

	程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。字节码解释器工作时通过
改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等功能都需要依赖这个计数器来完。
	在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次
运行到哪儿了。
	另外,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各线程之间计数器互
不影响,独立存储,我们称这类内存区域为“线程私有”的内存。

	为了保证线程中的局部变量不被别的线程访问到,虚拟机栈和本地方法栈是线程私有的。

string和stringbuilder和stringbuffer的区别

首先,string是由final修饰的字符串,所以其长度不可变,底层是final修饰的char类型数组。
如果使用string进行字符串拼接100次,就需要创建100个对象,期间需要给每个对象分配空间以及需要创建时间,频繁创建对象就需要大量时间,中间的无用对象就需要垃圾回收机制进行GC,也需要时间

stringbuffer和stringbuilder,它们的底层也是char类型数组,与string不同的是没有用final修饰,所以他们都是可变的。拼接字符串扩容是扩大1.5倍,把 初始容量是16。
stringbuffer每个方法都是由sychnolize修饰的所以是线程安全的,但每次都有加锁释放锁的额外开销,因此stringbuilder的效率更高一点。

.hashmap、hashtable、currenthashmap的区别
https://www.cnblogs.com/heyonggang/p/9112731.html

jdk1.7以前 hashmap底层是数组加链表实现的,8之后是数组加链表或数组加红黑树实现。
hashmap是非线程安全的,可允许有空值空键,且存在数组的第零个位置,固定不变的。hashtable是由sychonlize修饰的是线程安全的,适用于多线程。
hashtable和currenthashmap都是加锁、线程安全的。
concurrenthashmap锁分段技术:首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。
hashmap初始容量是16,扩容机制是2 * oldsize.自定义初始容量时,因为size必须为2的指数幂。
hashtable初始容量是11,扩容机制是2 * oldsize+1。

自旋锁到底是什么东西,简书。

hashcode和equals

hashcode是调用hashcode方法得到的散列值,当往集合中插入元素时,且集合中不允许有重复元素。若使用equals方法比较时,需要逐个比较,但若存在一万条数据时,就要进行一万次equals方法,效率低下。
此时使用hashcode方法的作用就体现出来,当向集合中插入元素,先调用这个对象的hashcode方法得到对应的哈希值,若集合中不存在此哈希值,直接插入,若存在相同hashcode值,再调用equals方法进行进一步比较,相同的话就不存了。从这里可以看出,hashCode方法的存在是为了减少equals方法的调用次数,从而提高程序效率。

面向对象的特征

封装:将对象的属性和方法的代码封装到一个类中,供外部调用,实现高内聚低耦合,使用这完全不用关心如何实现,只需要知道怎么使用就OK了。
抽象:将相同的类的共同特征总结出来,构造成类的过程。抽象包括数据抽象以及行为抽象。数据抽象变成类的成员变量(public int age),行为抽象成类的成员函数(方法:eat())。抽象只关心成员变量以及成员函数,并不关心具体的实现细节。
继承:继承是从父类集成到已有的信息创建新的类,并可扩展新的功能。常用在把共同的功能、属性作为父类,供其他子类使用。
多态:多态分为一下两种,有三个存在必要条件:继承、重写、父类引用指向子类。
编译时多态:比如重载
运行时多态:比如重写

  1. 方法重写,子类继承父类并重写父类已有的方法。
  2. 用父类型引用来引用子类型对象,这样可以实现调用同样的方法会根据子类对象的不同表示出不一样的行为。Map<String,String> map = new HashMap<>();

成员变量和局部变量

  1. 成员方法定义在本类中,本类中有效,存在于堆中,随着对象的产生而存在,消失而消失。
  2. 局部变量定义在方法内部,在方法内有效,存在于栈内存,随着方法的调用而存在,结束而释放。
  3. 方法中的局部变量使用final修饰后,放在堆中,而不是栈中。
  1. 构造函数

用于给对象初始化,构造函数可以有多个重载的构造函数。且构造函数只初始化一次。

创建一个对象内存都做了哪些事情?

  1. 先将对应类的class文件加载进内存。(Person.class)
  2. 将main方法押进栈空间,在栈内存分配一个变量P。
  3. 在堆内存分配一个空间,存new出来的东西,并进行初始化。
  4. 将new Person()的首地址指向栈内存的P。这时P变量就引用了Person实例。

说一下java内存管理机制

java内存的组成部分有:堆、栈、方法区、程序计数器、本地方法栈。
栈存放数据的基本类型和变量、对象的引用。(int i=2;String s=“aaa”;String s1=new String(“aaa”),其中i=2,s,s1都放在栈)
堆和方法区属于线程共享,其余三个属于线程私有,且不存在垃圾。
堆主要存放类的实例化对象,方法区主要存放编译后和方法相关的信息。
方法区主要存储类信息、常量池、静态变量等。运行时常量池是属于方法区的一部分。
99%的垃圾存在堆中,jvm调优指的就是调堆。
字符串常量池存在于堆,运行时常量池存在与方法区。
方法区的垃圾回收主要有两种,分别是对废弃常量的回收和对无用类的回收。

  1. jvm都有哪些?

hotspot (sun) 、J9 (ibm) 、Jrocket (BEA)。

什么是线程共享?

假如String a = " s"; String b=“s”;
a属于引用,存放于栈中,“s"存放于常量池,
此时b也存在于栈中,因为常量池已经存在"s"字符串,所以其引用也会指向同一个"s”,而不会放一个新的"s"在常量池中。此时,"s"就属于共享状态。

数组长度为n,数的范围{0,n-1};数组元素随机排放,可能有重复值,怎样判断是否有重复元素?

把元素遍历存到hashset集合里,然后得到set集合的size和n比较。

二进制的位运算

<< : 左移运算符,num << 1,相当于num乘以2  低位补0
>> : 右移运算符,num >> 1,相当于num除以2  高位补0
>>> : 无符号右移,忽略符号位,空位都以0补齐
 % : 模运算 取余
^ :   位异或 第一个操作数的的第n位于第二个操作数的第n位相反,那么结果的第n为也为1,否则为0
 & : 与运算 第一个操作数的的第n位于第二个操作数的第n位如果都是1,那么结果的第n为也为1,否则为0
 | :  或运算 第一个操作数的的第n位于第二个操作数的第n位 只要有一个是1,那么结果的第n为也为1,否则为0
 ~ : 非运算 操作数的第n位为1,那么结果的第n位为0,反之,也就是取反运算(一元操作符:只操作一个数)

URL、URI和URN三者之间的区别
URI:统一资源标识符
URL:统一资源定位符
URN:资源名称

我们一起来看下面这个虚构的例子。这是一个URI:
http://bitpoetry.io/posts/hello.html#intro
我们开始分析
http://
是定义如何访问资源的方式。另外
bitpoetry.io/posts/hello.html
是资源存放的位置,那么,在这个例子中,
#intro
是资源。
URL是URI的一个子集,告诉我们访问网络位置的方式。在我们的例子中,URL应该如下所示:
http://bitpoetry.io/posts/hello.html
URN是URI的子集,包括名字(给定的命名空间内),但是不包括访问方式,如下所示:
bitpoetry.io/posts/hello.html#intro

一次完整的HTTP请求发生了什么?
https://blog.csdn.net/qq_40804005/article/details/82876209

**1.域名解析:浏览器解析域名获得服务器IP地址。**
	怎么解析到ip地址:
	1. 浏览器会到自身的dns缓存中查看是否有该域名对应的ip地址,有且未过期,解析成功。
	2. 浏览器自身的dns缓存没有后到系统的dns缓存中查找,有且未过期,解析成功。
	3. 系统dns缓存没有,尝试读取hosts文件,看里面有没有对应的IP地址,有且未过期,解析成功。
	4. 浏览器就会发起一个DNS的系统调用,就会向本地配置的首选DNS服务器发起域名解析请求。
**2.发起TCP三次握手**
**3.建立TCP连接后发送http请求**
	拿到IP地址及端口号后,会向服务器的web程序的对应端口号发起TCP的连接请求。
	 请求包括:
>	 请求行=>1.请求方法 2.请求URL 3.http协议版本
>	 请求头=> 包括若干属性(浏览器类型、识别的资源、主机名),服务器据此获取客户端的信息。
>	 请求体=> 请求头和请求体之间空一行,请求体包括请求的参数。
**4.服务器响应http请求,并返回给浏览器资源页面**
	在响应中唯一与请求真正的区别在于第一行中用状态信息代替了请求信息。  HTTP/1.1 200 ok
**5.浏览器解析html代码**
	浏览器拿到HTML文件后,就开始解析HTML代码,遇到js/css/image等静态资源时,到服务器去下载,建立http连接。
	此时要请求的资源可能比较大,所以设置Connection:keep-alive。
**6.浏览器渲染到页面呈现给用户**

hosts文件有哪些其他的作用?

当我们要直接进入我们平常进过的一些网址时,只要我们输入网址的前面一点部分,整个网址都会在栏目里面显示出来,这样让我们方便多了。而这个就要归功于hosts文件。因为有hosts文件的存在,我们常用的那些网址以及与它对应的ip地址就会被记录在电脑的数据库中,我们在使用浏览器的时候才会更方便。

1.加快域名解析
2.域名重定向,用于屏蔽网站,可设置把某些网站映射到其他IP地址对应的网站。
3.更改域名为指定的虚拟域名。

设计模式之饿汉、懒汉

https://blog.csdn.net/yeyazhishang/article/details/90445330

饿汉式:在类加载的时候就进行类的实例化,避免了多线程的同步问题。
缺点是若该实例没用被用到,内存就被浪费了。

public class SingleTon{
	public final static SingleTon INSTANCE = new SingleTon();//创建类的实例,这个方法是public的,是全局访问的接口
	private SingleTon(){//无参构造
	}
	public static SingleTon getInstance(){//调用方法返回类的实例
		return INSTANCE;
	}
}

同步懒汉式:只有在方法第一次被访问时才会实例化,达到懒加载的效果。
加锁,保证了同一时刻只能有一个线程访问并获得实例。
缺点:因为synchronize修饰整个方法,每个线程访问都要进行同步,而其实这个方法只执行一次实例化就够了,每次同步效率低下。

public class SingleTon{
	private static SingleTon instance = null;
	private SingleTon(){
	}
	public static synchronize SingleTon getInstance(){//调用方法时进行类的实例化,这个方法是public的,是全局访问的接口
		if(instance == null){
			instance = new SingleTon();
		}
		return instance;
	}
}

双重检查懒汉式

public class Singleton {
    private static volatile Singleton instance;//volatile同步锁
    private Singleton() {}
    public static Singleton getInstance() {//这个方法是public的,是全局访问的接口
        if (instance == null) {
            synchronized (Singleton.class) {//synchronize锁住代码块
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

单例模式的优缺点
优点:单例类只有一个实例,节省了内存资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
缺点:单例模式一般没有接口,扩展的话除了修改代码基本没有其他途径。

hashmap怎么存储的?

首先,hashmap底层是数组+链表 或 数组+链表+红黑树。数组里存储的是map键值对的key的hashcode值,
而hash值是怎么散列到数组中呢?

先知道数组的长度是2的指数次幂,有了hashcode值,先把hashcode无符号右移16位,
这个长度正好是hashcode的一半,拿右移后的二进制数与hashcode值进行异或运算,(做扰动)
获取到的新二进制数与数组的(size-1)进行与运算,获取到的整数就是要存到数组的下标。

JDK1.8源码中,执行树形化之前,会先检查数组长度,如果长度小于64,则对数组进行扩容,而不是进行树形化。

jvm加载、连接、初始化 三者统称类加载或类初始化

编译:.java文件编译后生成.class字节码文件
加载:类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并为之创建一个java.lang.Class对象,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang.Class对象实例
连接:细分三步
  验证:格式(class文件规范是否符合当前虚拟机的要求) 语义(final类是否有子类) 操作
  准备:静态变量赋初值和内存空间,final修饰的内存空间直接赋原值,此处不是用户指定的初值。
  解析:符号引用转化为直接引用,分配地址
初始化:有父类先初始化父类,然后初始化自己;将static修饰代码执行一遍,如果是静态变量,则用用户指定值覆盖原有初值;如果是代码块,则执行一遍操作。

什么是符号引用:在编译时, Java类并不知道所引用的类的实际地址, 因此只能使用符号引用来代替. 比如org.simple.People类引用了org.simple.Language类, 在编译时People类并不知道Language类的实际内存地址, 因此只能使用符号org.simple.Language来表示Language类的地址.

在这里插入图片描述

比如我们定义了 public static int value=111 ,
那么 value这样的静态变量在准备阶段的初始值就是 0 而不是111(初始化阶段才会赋值)。
特殊情况:比如给 value 变量加上了 fianl 关键字 public static final int value=111 ,
那么准备阶段 value 的值就被赋值为 111

什么是字节码?好处是什么?

1. 字节码是程序通过编译器编译后的二进制文件,也就是把.java文件转换成.class文件。
2. 好处就是一次编译处处运行,也就是java的与平台的无关性。

C++和java的不同有哪些?

  • java没有指针这个概念。
  • java有内存管理机制,自动进行垃圾回收。
  • java的类是单继承多重继承的,C++的类可以多继承的。

java中类中属性、变量不想进行序列化怎么办?

  • 可以用transient关键字修饰该属性,注意transient只能修饰属性,不能作用于方法和类。

Collections 工具类和 Arrays 工具类常见方法
关于三次握手的面试题

TCP建立连接的三次握手中,第二次握手发送的包会包含的标记,最正确的描述是?
A. SYN
B. ACK
C. SYN, PSH
D. SYN, ACK
解析:
三次握手:(1(B)->[SYN]->(A)
假设服务器A和客户机B通讯。当A要和B通信时,B首先向A发一个SYN(Synchronize)标记的包,告诉A请求建立连接。
(2(B)<-[SYN/ACK]<-(A)
接着,A收到后会发一个对SYN包的确认包(SYN/ACK)回去,表示对第一个SYN包的确认,并继续握手操作。
(3(B)->[ACK]->(A)
B收到SYN/ACK包,B发一个确认包(ACK),通知A连接已建立。至此,三次握手完成,一个TCP连接完成。
答案:D

http1.0和http1.1有何区别?

   http1.0规定浏览器和服务器只能保持短暂连接,浏览器每次请求服务器都需要经过三次握手建立tcp连接,
服务器完成请求后就断开连接。
   http1.1支持长连接,即在同一个tcp连接中可以传送多个http请求和响应,只需在请求头设置的Connection 
为keep-alive。即可以多次请求和响应,关闭时在请求头connection设置close即可关闭连接。这样做的好处
在于可以减少建立和关闭连接的消耗和延迟。默认就是长连接。
   http1.1还增加了host字段,即在请求头部将HOST设置上本机IP地址,若没有回报404.
   http1.1还加入了新的状态码100.当客户端向服务器发送文件资源时,客户端会事先发送一个只带头域的请求。
服务器会发送100的状态码作为临时响应表示可以接受此资源,可以继续发送。
   HTTP/1.1中引入了Chunked transfer-coding来解决上面这个问题,发送方将消息分割成若干个任意大小的数
据块。这种方法允许发送方只缓冲消息的一个片段,避免缓冲整个消息带来的过载。

TIME_WAIT和CLOSE_WAIT的区别

	当浏览器和服务器通信要进行四次挥手时,客户端发送fin请求断开连接(一次挥手),服务器收到后就进入
CLOSE_WAIT阶段,而后发送ack确认收到fin请求(二次),当服务器响应完发送fin请求断开(三次),客户端收到
后进入TIME_WAIT阶段(主动),此时客户端发送ack确认断开(四次),直到服务器收到ack时,CLOSE_WAIT结束。
TIME_WAIT是属于客户端一方的,时长是2MSL(四分钟),目的是确保最后一个ack能够成功抵达服务器。

在这里插入图片描述
TCP是怎么保证传输可靠的?

1. 序列号确认号校验:ack包含下一个数据的开始索引。(ACK(1,2000))=>(ACK(2001,3000))
2. 超时重传:当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个
   确认,将重发这个报文段。
3. 校验和:TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何
   变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
   (ACK(1,2000))=>(ACK(2001,3000))
4. 三次握手四次挥手

传了syn,为何还要传ack?
	syn是为了确认收到客户端的信息,之后再传ack是为了校验字符=>(ACK(1,2000))=>(ACK(2001,3000));

在这里插入图片描述
反射原理和获取class三种方式

1.Person p1 = new Person();
	p1.getClass();
	
2.Person2.class;    (直接类名.class)

3.Class.forName("Person3");

注意:这三个获取到的class是同一个对象,person1,person2只是这个对象的不同实例。

Class.forName()和ClassLoader的区别?
相同点:两者都可以将类加载进内存。
不同点:通过反射把类加载进内存会初始化,给静态变量赋值。而通过ClassLoader只会加载进内存不会初始化。

Class.forName()和ClassLoader的区别

通过反射可以获取类里的各种属性、方法名…

getName():获得类的完整名字。
  getFields():获得类的public类型的属性。
  getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
  getMethods():获得类的public类型的方法。
  getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
  getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名
   字,parameterTypes 参数指定方法的参数类型。
  getConstructors():获得类的public类型的构造方法。
  getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造
   方法的参数类型。
  newInstance():通过类的不带参数的构造方法创建这个类的一个对象

四种引用类型

  • 强引用类型:对象被强引用类型引用是不会被垃圾回收。
  • 软引用类型:对象被软引用类型引用时,内存不足时被垃圾回收。和引用队列一起使用,回收后,jvm就会把这个软引用加入到与之相关联的引用队列中。常用于缓存数据。
  • 弱引用类型:对象被弱引用类型引用时,不管内存够不够都会被垃圾回收。和引用队列一起使用,回收后,jvm就会把这个软引用加入到与之相关联的引用队列中。
  • 虚引用类型:和引用队列一起使用,一般用于追踪垃圾收集器的回收动作。

使用软引用的情况较多,因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生。

垃圾回收算法Eden和survivor的比例是8:1。

  • 复制算法:多用于新生代,把from区gc后幸存的复制到to区。
    优点:快、不会产生内存碎片。
    缺点:因为to区一直是空的,所以多占了一份内存空间。浪费内存。复制次数太多效率变低。
  • 标记清除:多用于老年代,把伊甸园区的对象做标记,被标记的将会在垃圾回收的时候被清理。
    标记: 标记的过程其实就是,遍历所有的GC Roots,然后将所有的 GC Roots可达的对象标记为存活的对象。
    优点:实现简单、必要时才回收(内存不足时)。
    缺点:会产生内存碎片。产生内存碎片的后果是,一个大的对象无法分配到足够的空间,从而会提前触发GC操作。
  • 标记整合:多用于老年代,把被标记的对象清除之后,剩下的空间整合到一起,形成连续内存。
    优点:不会产生内存碎片。
    缺点:因为会给对象重新分配引用,会大量浪费时间。效率低。
类需要同时满足下面3个条件才能算是“无用的类”:
1、该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。
2、加载该类的ClassLoader已经被回收。
3、该类对应的java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

动态代理

代理模式:在调用处不直接调用目标类进行操作,而是调用代理类,然后通过代理类来调用目标类进行操作。在代理类调用目标类的前后可以添加一些预处理和后处理操作来完成一些不属于目标类的功能。
  • spring原生JDK代理:实现代理必须实现接口;
  • Cglib:只需一个类,无需接口。通过继承子类增强父类。父类不能用final。

final关键字的作用

  1. 定义在类上,该类不能被继承。
  2. 定义在方法上,该方法不能被重写。
  3. 定义变量,该变量定义完不能被修改。被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的。
  4. 被final修饰的常量,在编译阶段会存入调用类的常量池中。

Java中访问修饰符public、private、protecte、default的意义

			public>protected>default>private
  • 主要标示修饰块的作用域,方便隔离防护。
  • 修饰符的存在可以在包与包之间、类与类之间产生一种权限的关系.。
    在这里插入图片描述

什么是序列化?
什么是 java 序列化?什么情况下需要序列化?
序列化的使用场景:

  • 本地存储
  • 网络存储

记住:凡是离开内存的信息都要进行序列化。将字符串转换成字节流,以便网络传输和存储。
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值