Java 学习线路图是怎样的?
就我个人的学习路线而言,在这里做一个总结:
1.我首先先学习HTML,CSS,JavaScript,慕课网上有很多的教程,可以在上面把所有的教程都刷一遍,学完后,能熟练使用基本的HTML标签,常见CSS属性,js语法等。
2.学完前端方面的基础知识后,这时候可以看java se部分了,我当初是看的某某谷的宋红康老师的视频,讲的非常的好,入门强烈推荐。当java基础学完后,这时候就可以做一个小型的J2SE项目把以前学的java基础的知识用起来,我当时看的是一个坦克大战的小游戏项目视频。
3.接下来,学习jdbc,数据库连接池,还有 Oracle、MySQL、sql server 数据库常用的SQL语法,要具备能够编写SQL脚本的能力,像什么多表关联,数据库三范式等等,都要知道。
4.数据库学完了,这是就可以看java web的知识,比如JSP、servlet、session、cookie、EL表达式等等,java web 基础学完后,可以在此基础上写个小项目,比如XXX管理系统,XXX网上书城等,在实战中巩固自己所学的知识。
5.以上知识学完了,就可以学习主流的框架,像 Spring、Spring MVC、Struts、Hibernate、Mybatis,因为这些框架在公司的实战开发中是比较常见的。
6.最后可以做一个完整的项目(SSH,SSM),比如你可以做一个网上商城项目,将以上所学的内容进行整合,这样我觉得基本上算java入门了吧。
7. 其他的扩展技能,像比如项目管理工具 maven、java 开发工具 IntelliJ IDEA、权限框架 shiro、作业调度框架Quartz、非关系型的数据库redis等等,在有了入门的基础后,都可以进行学习,提高个人的专业技能素质。
我当初是大三下学期开始自学,时间上差不多花了一个多学期吧,中间踩了无数坑,但是很庆幸自己一路坚持下来了,现在在一家做跨境电商的公司做Java开发,虽然现在没啥大的成就,但是每天过的开心就好。加油,题主,你可以的!寥寥数语,与君共勉。
做为一名新手,首先你要明白一个真相,《21天精通JAVA》是不现实的。然后你要做的是,摆正心态,脚踏实地,打好基础。
那么这个过程嘛,这样的:
第一步,首先你要了解JAVA
为什么要了解java? 这个当然很重要你既然要学习java肯定要了解它,它可以干什么,做什么,有什么特性,用在哪儿?什么多线程,什么多态性,什么面向对象,什么移植性balabalabala等等等,对不对,以后你真成了高手了不还可以和人家家谈谈java的历史嘛,哪怕某天有人问你java和javascript有什么区别,你也不会回答说“多了个script”吧。
Java ( 计算机编程语言 ) - 百度百科
Java 简介
第二步,JAVA程序环境
了解了语言历史,特性之后,也该动动手了吧,不能光看不练嘛,那么要动手肯定要先搭建环境。
- 下载JDK
- 配置环境变量
- 验证配置环境变量
Java 开发环境配置
JDK下载
第三步,JAVA基本程序设计结构
环境搭建好了就可以开始边学边练习了,在这我简单分下知识点:
- 数据类型 >> Java 基本数据类型
- 变量 >> Java 变量类型
- 运算符 >> Java 运算符
- 字符串 >> Java基础字符、字符串
- 输入输出 >> JAVA输入输出流学习
- 控制流程 >> JAVA流程控制
- 大数值 >> JAVA大数值
- 数组 >> Java 数组
第四步,对象和类
面向对象程序简称oop,是当今主流程序设计范型,面向对象程序设计于面向过程程序设计还是有一定的区别的,如果不懂建议好好学习。
- 类,使用现有类 >> Java经典教程什么是类? Java使用现有的类
- 用户自定义类 >> Java用户自定义类
- 静态域于静态方法 >> Java静态域与静态方法
- 方法参数 >> java中方法的参数传递机制
- 对象构造 >> JAVA对象的构造和初始化
- 包 >> Java 包(package)
- 路径类 >> JAVA类路径说明(新手必读)
- 类的设计技巧 >> Java中类的设计技巧
第五步,继承
- 超类,子类 >> Java 继承,类,超类和子类
- Object >> Java中的Object对象理解
- 泛型数组列表 >> 泛型数组列表
- 对象自动打包 >> Java对象包装器 自动打包解包
- 枚举类 >> Java 枚举类的基本使用
- 反射 >> Java反射机制详解
第六步,接口 and 内部类
- 接口 >> Java接口_百度百科
- 对象克隆 >> JAVA对象的克隆
- 接口和回调 >> 回调函数、Java接口回调总结
- 内部类 >> 内部类详解
第七步,Swing图形程序
- Swing框架 >> Swing开发包
第八步,事件处理
- 事件处理 >> Java程序设计-事件处理
- 动作 >> JAVA入门之Swing如何监听用户动作
第九步,部署应用程序
- jar文件 >> java 可执行Jar包打包方法
- Java web start >> Java Web Start完整的开发和调用
- Applet >> 教你构建第一个Java Applet程序
第十步,异常,日志,断言和调试
- 处理异常 >> Java中如何正确处理异常
- 捕获异常 >> 深入理解Java异常处理机制
- 断言 >> Java断言开启、断言使用
- 记录日志 >> JAVA日志记录方法
- 调试 >> Java程序员应该知道的10个调试技巧
第十一步,泛型程序
- 约束和局限性 >> Java泛型?约束和局限性
- 继承规则 >> Java泛型 泛型类型的继承规则
- 通配符类型 >> java 泛型详解(普通泛型、 通配符、 泛型接口)
- 反射和泛型 >> Java泛型和反射机制
第十二步,集合
- 集合接口 >> Java 集合中主要接口的介绍
- 集合框架 >> Java - 集合框架完全解析
- 集合算法 >> Java的集合之算法篇
- 遗留的集合 >> java集合--遗留的集合
第十三步,多线程
- 线程属性 >> JAVA线程5 - 线程属性
- 同步 >> Java 多线程同步的五种方法
- 阻塞队列 >> Java中的阻塞队列
- 线程安全的集合 >> Java多线程理解:线程安全的集合对象
- 执行器 >> Java多线程--执行器
- 同步器 >> Java多线程编程之同步器
----------------------------------------
如果你刷完上面那些知识点并且可以熟练运用,那么恭喜你你已经成功迈入java的大门, 这个时候需要做一些完整的项目来的获取更多的经验值升级,同时你可能会遇到更多的知识点:比如:流和文件,I/O,XML,树,awt,分布式对象以及各种框架等等等,假如你足够努力,在这个过程中你会成长的很快,但良好的基础会让你走的更远。
如果你对Java或开发感兴趣的可以关注我专栏,极乐科技 - 知乎专栏
不多说,直接上图,希望有兴趣想学的同学,能够有个相对明细的参照。
在这里我也同时提醒查看的本路线的同学,这套路线是依我个人的工作经历所总结出来的相关知识点。分为四个阶段,内容很多。具体你需要花多少时间才能够全部学完这个因人而异,毕竟没人知道你在学习的过程中是否会时时被打断。
然后就是,如果你不是一个能接受新的挑战的人,就不建议你学习了。毕竟编程可不是一招鲜吃遍天的,这只是一个开端,后续你可能还有更多需要学习的,更多挑战。如果你是一个喜爱挑战并解决问题的,那么欢迎你进入Java的世界!
Java学习前的一些准备
- JDK - (Java SE Development Kit)
JDK是Java开发所需要的环境,就跟我们想玩某个网游一样,玩之前一定是需要先安装相应的程序包的。 那这个JDK就是我们准备登陆Java大陆前需要安装的一个程序包。
下载地址 : Java SE - Downloads
- IDE - (Integrated Development Environmen)
IDE是集成开发环境,一般集成开发环境都会带有JDK,可以使用自带的JDK也可以使用我们下载的JDK,不同的IDE配置不同。Java常用的IDE有Eclipse、MyEclipse、IntelliJ IDEA。IDE具备代码分析、补全、变异、调试等常用功能,可以大大的提高开发人员的编程效率。
eclipse下载地址 : https://www.eclipse.org/downloads/ MyEclipse下载地址 : MyEclipse官方中文网 IntelliJ IDEA : IntelliJ IDEA: The Java IDE for Professional Developers by JetBrains
- 书籍推荐
阶段大致细节
1、入门基础
- Java简介
- 了解什么是Java;代码语法基本格式;输出表达式。
- 了解Java大致的编译以及执行过程
- Java语言基础、循环、数组 ; 了解类和对象
- 掌握Java的基本数据类型和引用数据类型有哪些;
- 掌握强制数据类型转换和自动类型提升规则;
- 常量如何声明及赋值;
- 循环的语法及作用;
- 数组的声明及定义;
- 掌握类的概念以及什么是对象。
- OOP封装、继承、多态
- 面向对象的三大特征,本节内容非常重要也相对来说较为难以理解,一定要耐下心来好好理解。
- java.util.*包下的常用类
- util包下的Collection、Comparator、Iterator、List、Map、Set接口都很重要,着重看一下他们的实现类,如:ArrayList、LinkedList、HashSet、HashMap、Hashtable、TreeMap、TreeSet等。
- java.lang.*包下的常用类
- lang包下的基本数据类型对应的包装类(Byte、Short、Integer、Long、Double、Float、Character、Boolean);
- 字符串相关的类String、StringBuffer、StringBuilder。
- IO流操作,多线程及Socket
- 掌握IO读写流相关的类,了解字节流,字符流和字符流缓冲区;
- 掌握线程的概念,多线程的创建、启动方式,锁和同步的概念及运用;
- 掌握Socket通信的概念,如何声明客户端服务端,如何完成双端数据通信。
- 泛型、数据库基础(Mysql)及JDBC
- 到了数据库前,我们可以看看泛型以及反射的一些基础案例
- 掌握数据库的基本概念,Mysql的安装、启动与停止
- Mysql数据库客户端的安装与使用
- JDBC的概念,在Java中使用Mysql驱动包连接Mysql
Mysql社区版下载 : Download MySQL Community Server 客户端连接工具 Navicat for Mysql下载 : MySQL Database Administration and Development Tool
通过第一阶段的学习掌握Java语法和常用类,数据库入门技术相关知识。让自己对于存储,IO,这些有个大概的了解。这时候,暂时不需要花大量的精力以及篇幅去学习多线程和Socket,当然这里不是说他们不重要,而是对于现阶段的你,或许很难非常清晰的明白以及了解他们具体的作用。这里第一节忽略掉了Swing,Swing章节的内容可以不学,因为在实际的工作中基本上没有用武之地。
使用第一阶段的技术完成一个小型的系统,找一个自己做容易理解的系统练练手,比如超市管理系统、成绩管理系统等等这类需求简单却能讲整章内容结合起来使用的项目。当然这个时候可能会有人觉得没有图形界面没法完成系统操作。实际上我们可以通过Console的输入输出来做系统界面。
新手在第一阶段的学习时,是最难熬的,因为这个时候需要背的东西特别多,且不再像看小说一样,什么东西都能看明白。路就变成了前面熟悉,左右陌生。这个时候人的求知欲作祟,往往会把自己带着偏移了方向,因为我们自己也不知道这样走对不对。渐而远之,也就慢慢放弃了。而这样的放弃,是最不值得的。所以,学习Java一定要按照某一个大纲,一直往下不要往其他地方偏,先走完一遍之后,再回头慢慢捡。
2、前端基础
- HTML基本标签、表格、表单和框架;
- 掌握网页的基本构成;
- 掌握HTML的基本语法;
- 表格的作用以及合并行、合并列;
- 表单标签的使用,提交方式get/post的区别;
- 框架布局的使用
- CSS样式表;
- 掌握CSS的语法及作用,在html中的声明方式;
- 掌握CSS布局的函数使用;
- 掌握CSS外部样式的引入。
- JavaScript;
- 掌握JS的语法及作用,在HTML中的声明方式;
- 掌握JS的运行方式;
- 掌握JS中的变量声明、函数声明、参数传递等;
- 掌握HTML中的标签事件使用;
- 掌握JS中的DOM原型
上述三节都可以查看w3school : HTML 系列教程
- jQuery
- 了解如何使用jQuery,下载最新版或者老版本的jQuery.js
- 掌握选择器、文档处理、属性、事件等语法及使用;
- 能够灵活使用选择器查找到想要查找的元素并操作他们的属性;
- 动态声明事件;
- 动态创建元素。
jQuery文档 : jQuery API 中文文档 | jQuery API 中文在线手册 | jquery api 下载 | jquery api chm
- BootStrap;
- 掌握BootStrap的设计理念,以及使用方式。这是我们需要接触的第一个前端框架,使用起来也很简单;
- 掌握BootStrap的栅格系统、表单、全局样式、分页工具栏、模态框等。
- Servlet
- 掌握Java中的Web项目目录结构;
- 掌握Java Web项目的重要中间件Tomcat;
- 掌握Servlet中的Request和Response;
- 掌握Servlet的基本运行过程。
- 掌握Servlet的声明周期
- 动态网页技术
- JSP在Java Web中的角色;
- JSP的编码规范,以及JSPServlet;
- JSP显示乱码的解决办法等。
- JSP数据交互
- JSP中如何编写Java代码,如何使用Java中的类;
- JSP中的参数传递。
- 状态管理Session和Cookie
- 掌握Session的作用及作用域;
- 掌握Cookie的作用及作用域;
- 掌握Session及Cookie的区别,存储位置,声明周期等;
- 掌握Session及Cookie分别在JSP和Cookie中的使用
- JSTL和EL表达式
- 使用EL表达式输出page、request、session、application作用域中的值
- 使用JSTL来做逻辑判断或循环控制
- JNDI数据库连接池
- JNDI的作用以及如何使用JNDI连接数据库
- 分页和文件上传
- 掌握在JSP中如何使数据达到分页的目的;
- 掌握在JSP表单中如何上传文件,Servlet如何处理上传请求(Commons-Fileupload、Commons-IO)。
- Ajax
- 掌握Ajax的基本概念;
- 掌握jQuery中的Ajax请求;
- 掌握JSON
- Filter、Listener;
- 掌握Filter和Listener
- 掌握Session过滤器和编码过滤器
通过第二阶段了解前端相关的技术,如果你喜欢前端各种酷炫的效果,那么就深入学习JS、CSS。不大感兴趣的话,就浅尝辄止,并重点学习Servlet、Filter、Listener。重点学习,重点学习,重点学习。 重要的话说三遍!
学习完第二阶段的内容之后,就可以进行B/S版本的系统开发了。这个时候我们可以挑选个稍微复杂点儿的项目来练练手,能找到商业项目练手的那是最好不过的,没有的话,就写写学生管理系统,档案管理系统,人事管理系统之类的练练手吧。
最后说一下本阶段的前端知识,如果将jQuery和Bootstrap学的差不多了的话,再看EasyUI这之类的前端框架也基本上都是照着API用就行了。别害怕看API,看API将是你以为的整个职场生涯必不可少的一个技能。
3、 主流技术应用
- Mybatis的应用
- Mybatis的Mapping与实体映射;
- Mybatis中的SQL语句写法;
- Mybatis的缓存。
- Spring应用
- Spring容器的作用;
- Spring的AOP和IOC;
- Spring托管Mybatis事务;
- SpringMVC的应用
- SpringMVC中的控制器注解、请求注解、参数注解、响应注解等;
- SpringMVC中的静态资源处理;
- SpringMVC的容器。
- Spring+SpringMVC+Mybatis整合
- SSM的整合使用;
- Spring容器和SpringMVC容器
- Redis+Mysql的查询优化设计
- Redis的安装与连接;
- Redis常用命令及各命令使用场景;
- Redis存储机制;
- Redis的持久化机制。
- 任务处理相关
- HttpClient模拟请求
- Quartz定时任务
- 常用工具
- Excel&World导入导出
- 短信&邮件发送
- Maven
- Maven的作用
- Maven项目的创建
- Maven的生命周期
- Maven中央仓库及私服
- Log4J2日志
- FastDFS的使用
- 什么是分布式文件系统;
- 分布式文件系统解决的问题是什么;
- FastDFS的使用
通过第三阶段了解目前Java领域比较经典的三大框架,了解他们的大概功能,并加以使用。通过使用SSM开发一个简易CRM之类的项目来加强了解,理清楚框架的大致原理。搞清楚这三个框架之间的作用域以及角色。理解Redis作为内存数据库与MySQL这类关系型数据库的区别,并能使用常用的Jar包完成模拟请求,定时任务等相关系统常用功能的开发。并能够通过Maven创建SSM项目,整合Log4j或其他的日志包。了解FastDFS的作用,并理解图片上传至文件服务器和上传到tomcat之间的区别
在第三阶段的内容学习完了之后,就应该对整个系统研发有个大概的印象,实际上这个时候,独立完成一个系统之后,再回过头来仔细思考下Servlet+JDBC+JSP与SSM实现项目的相同点及区别。这样会让你更加的有收获。并能够理解非关系型数据库Redis的性能优势以及使用场景。
4、模拟实际项目开发
- SpringBoot 2.0的应用
- 了解SpringBoot的起源及优势
- 了解SpringBoot项目的格式以及创建方式
- yaml语法特性
- application配置文件及静态资源处理
- Thymeleaf模板引擎
- SpringBoot核心之WebMVCConfigurer
- Spring自定义错误处理
- SpringBoot日志引用及切换
- SpringBoot数据源和Mybatis
- SpringBoot-redis应用
- Struts2应用(了解即可)
- 通过学习Struts,了解什么是MVC;
- 掌握Struts是如何完成界面控制的;
- 掌握Struts的参数接收及传递;
- 掌握Struts的拦截器;
- 掌握Struts的OGNL和标签使用。
- Hibernate应用(了解即可)
- Hibernate在项目中的作用及优势;
- Hibernate中的hbm与实体类之间的关系;
- 什么是HQL,什么是关系映射(一对一,多对一,多对多);
- 了解Hibernate的事务、懒加载和缓存。
- Redis哨兵模式的搭建
- Linux操作系统
- Linux中的常用命令;
- Linux下的JDK、tomcat安装;
- Linux下的项目部署方式。
- Nginx的使用
- Nginx的作用;
- 反向代理和正向代理分别是什么;
- Nginx实现tomcat代理。
- Mysql集群方案
- Mysql集群的常用方案有哪些;
- Mycat中间件的概念
- Mycat的使用准则;
- 了解数据库的主从复制;
- 了解数据库的主备切换;
- 为什么需要主从和主备。
- Solr入门
- 什么是全文检索;
- Solr做搜索的优势是什么;
- Lucene、ElasticSearch、Solr之间的关系;
- Solr的安装与使用。
- JVM
- 回顾所有所学习到的知识,联系所有框架中的自定义容器、上下文来理解变量及对象的存储
- 理解垃圾回收是怎么一回事
- 理解集中回收算法
- 完全理解整个堆栈模型
通过第四个阶段了解更简单易用的SpringBoot,微服务应用和存储集群相关的概念及实现方案。让自己具备一个设计高可用,可扩展的项目框架视野。这样对于后面继续专研SpringCloud / Dubbo、zookeeper这些RPC相关的框架有很大的好处。
第四阶段的内容更加偏向于互联网技术栈,通过这一节的内容能够脱离出基本的增删改查,了解出了增删查改之后,需要了解的集群、系统性能优化、外部缓存服务器使用、集群负载等概念。这些思维对于后面的提高以及学习会很有好处。
我提到的这些东西都能搜到对应的资料,无非多踩点坑罢了。但是,看文档or项目永远进步不了。一定要上手敲,想再多也不如动手。有机会联系一名优秀学长,有个走在前面的人给你指路肯定比你自己走要快得多。
最后,一定要动手,一定要动手,一定要动手。把代码敲烂,你才会有收获,不要被视频诱导,敲一遍之后误认为你自己会了,如果第二天你起来时已经忘了昨天学习了什么的话,那说明你还是没学会。好好加油吧。
在所有的学习过程中,每一个节点都应该有相应的练习或者项目来进行练手,看再多的博文和视频都是不行的, 不能让自己的双手停下来,只有不停的敲打键盘,写出自己的项目,然后在实际的开发中学会如何使用debug,总结所有遇到的bug及解决思路,这样才叫做学习技术。所以,希望有兴趣的同学,能够好好努力,不要因为一点点难度就懈怠、放弃。开发这条路途,无论你工作多久,都会遇到各种奇奇怪怪的问题,以及形形色色的bug等着你去解决。
JAVA学习应该是由简到繁,由易到难,一步步的学习,最后成为 JAVA攻城狮。主要是四个阶段,如下:
- 阶段一 学习HTML 学习CSS Javascript jquery xml解析 Bootstrap
- 阶段二 JAVAse基础 mysql数据库 Powerdesigner JDBC JAVAWEB
- 阶段三 oracle struts2 Hibernate Spring
- 阶段四 Maven SpringMVC MyBatis
/*文章很长,但真心想学习的零基础朋友,请务必看完,绝不抖机灵*/
这篇文章是为了介绍自己自学用过的Java视频资料。
本套整合教程总共180+G,共450+小时,可用格式工厂转MP4格式,QQ影音加速播放。但考虑到绝大部分视频至少要看两遍,而且视频总时长并不代表学习时长,所以零基础初学者总学习时间大约为:
600小时视频时长 + 100小时理解 + 100小时练习,至少需要800小时。
你可能觉得自己能一天学习8小时,实际上平均下来每天能学4小时都算厉害了。因为有些时候你就是学不下去,或者某阶段视频内容太难光看完半天内容就够呛,或者其他事情耽搁了。如果周末你也是坚持学习,那么最理想状况下,6个半月就可以学完。但我知道那其实基本不可能。我自己从完全零基础,到学C语言,到学Java,除去中间断开的两个月,已经学习10个月。当然,这和我边工作边学习,以及没有人帮我找资料有很大关系。很多时间花在找资料上了。如果你已经经历过JavaSE的洗礼,会明白,我这篇回答对现在迷茫的你份量有多重。
一般来说,按本套教程,从零基础到达到工作后能被人带,至少需要8个月!培训班现在也需要6个半月。不过现在自学或培训出来的已经很难找工作了。
我不想和别人辩解这个,一般得到的回答是“谁说不好找,你自己学得垃圾而已!”。总之,没有朋友内推,我不推荐零基础的朋友冒险进这行,没你想得那么好的。各行各业都有值得做的工作。
以下正文:
我15年毕业,大学日语专业。16年9月18日开始决定学编程。
【1,启蒙阶段】
同样地,花了3天经历了入门语言选python还是C的纠结后,我最终选择看郝斌老师的C语言视频入门。具体学习方法看我的另一个回答,希望对你有帮助:零基础如何学习编程
这个阶段与其说学C,不如说懂一些基本的编程知识,比如:循环结构,数组,简单的内存分配原理,指针概念等。郝斌老师的C语言视频,对小白非常友好,启蒙教育做得很好!
如果时间不是很宽裕,可以直接从下面的JavaSE视频开始,看自己能否接受。
如果时间比较宽裕,喜欢循序渐进,培养兴趣了解一些计算机知识,那么可以看看。
我个人觉得郝斌老师讲课很有魅力,我喜欢听他唠嗑。像一位好朋友娓娓道来。
【2,JavaSE基础】
JavaSE阶段,建议完全零基础的朋友,先看毕老师的快速过一遍,再看刘意的。或者直接看刘意老师的,辅助看毕老师的。放心,完全零基础的朋友,一遍肯定学不会。所以同一套视频看两遍都算少了。另外,有时一个老师的观点是片面的,要结合不同老师的讲解才可能对一个知识点有更全面深刻的理解(前提是先把一个老师的讲解吃透)。所以我是建议刘意和毕向东的都至少看两遍。
具体建议后面会给出。
<对零基础学习者的建议>
0,看视频学习,不要看书学习。我自己是日语专业的,此前完全没有接触过编程,对编程是完全没概念的。知乎上很多人都说看视频慢,建议直接看优秀的书籍,所以我就买了C语言的一些书和Java的一些书(都是初学入门的),但都看不懂,看不下去。反而是后期跟着视频学习一段时间后,再翻开书本(其实几乎没看过书),慢慢能知道书里在讲什么了。大家千万不要觉得看视频会显得自己学习能力不够强。实际上,大学选择计算机专业的同学,又有多少比例是不靠老师上课,自己躲图书馆把编程学会的呢?从这个角度来说,看视频相当于大学课堂听课。并没什么不妥。
1,不懂的知识点视频多看几遍,如果视频有配套笔记,第二天起来复习一遍,加深印象。自己也可用word做笔记,写学习日志。JavaSE有不懂的,可以百度或谷歌,看看别人的技术博客。再回过头看视频可能就突然明白了。因为我也这么试过,对我帮助很大,希望你也能试试。
2,根据视频内容画思维导图!
画思维导图的好处在我看来至少有两个:
①理清讲解思路,让自己有全局观。初学Java,每一天的视频刚听完就基本忘得差不多了。很多知识点脑海中也只剩下一个名词,具体讲了什么已经记不得!做笔记长远来看是最省时间的。因为笔记内容都是自己消化过的,后期不用再去看视频复习(太麻烦了),直接看自己的笔记效率更高!反而蜻蜓点水,不做笔记一味求快的人,学到后面跟不上。因为这些知识点你只是听懂了,而不是理解,也没有实际编码操作过,印象是不深的!!
②方便日后复习,以及遗忘时的检索回忆。
下面是我的思维导图截图(windows可以使用Xmind)
思维导图可以很好地帮助我们理清知识点
思维导图要自己做,自己看,效果最好。看别人的基本没效果。
3,初级阶段不建议买任何书籍,专心看视频和附带的笔记足够了。包括知乎上推荐的《head first Java》,《疯狂Java讲义》,《Java核心技术》都不太适合现阶段完全零基础的我们。太厚,知识点太详细。要知道,我们现在刚学完C,才了解编程的循环语句而已。再怎么好的入门书籍,它对受众也是有一定要求的。而这个阶段的我们,就像小婴儿,即使给我们一辆带辅助轮的自行车,我们也骑不了...我买过一本《疯狂Java讲义》,就翻了几次。看着密密麻麻完全不熟悉的知识点,很烦躁很焦虑。当然,我不是说看书不好,只是本阶段不推荐。至少我从零基础到学习框架,从书本上学到的可能就占了0.5%,看博客学到的也比书本多。几乎完全是靠视频学来的。而且视频也有源码和笔记,已经很方便。
对零基础的学习者来说,JavaSE的学习非常困难。比如我,学了一个多月才学到毕老师的异常一章。之前在面向对象一章就已经很崩溃,哪知异常也这么抽象,完全不知道它是干嘛的....很多人是科班出身,早就忘了当初自己连软件都不会装的窘境。就像我们现在根本不会觉得用筷子还需要学习,但你爸妈当年为了教你用筷子,可是头疼过不止一次呢!
初学者也容易想走捷径。我相信很多人都会有这个想法:知识点太多太难,能否暂时止血工作需要的。其实JavaSE全是重点,培训班本身就是帮我们筛选掉不重要的知识点了。以刘意老师视频为例,面向对象(封装,继承,多态),异常,多线程,集合框架,IO,网络编程都挺难的。其中面向对象是JavaSE的重中之重,里面的知识点个人认为是最难的。后面的知识点都是建立在这之上展开的,没学好面向对象,后面就会稀里糊涂。
当然,也不是真的一点都不能跳,但最好完整地学下来。按照后面JavaWeb的学习来看:
面向对象是基石,JavaSE中最重要的一是集合,二是IO,希望大家学习这两个知识点时认真对待,多敲代码,多思考。
常用API里,String及其相关类StringBuilder, StringBuffer等必须熟悉,后面会不断用到。不学好的话,后面怎么死都不知道!
泛型一般只出现在集合中,个人觉得如果一时无法掌握,那么暂时会在集合中使用泛型就行了。
反射对于初学者来说是非常抽象的!!但它又无比重要。它虽然不是JavaSE的重点,但是它是JavaWeb很多难点的底层支撑,不懂反射,寸步难行。感到困惑时可以参考我的反射思维导图,完全是初学者不专业的解释。
链接:http://pan.baidu.com/s/1bp0b2HL
windows下载XMind软件打开。
>重点
面向对象☆☆☆☆☆
集合☆☆☆☆☆
IO ☆☆☆☆☆
String/StringBuffer/StringBuilder ☆☆☆☆☆
反射☆☆☆☆☆
泛型☆☆☆☆
>熟悉
异常,多线程
>先过一遍
GUI,网络编程,正则表达式
【3,JavaSE之后干嘛】
我当时学完毕老师的25天后,迷茫了很久...根本不知道下一步怎么走,该看谁的视频好一点。后来才知道毕老师原来还有35天、30天、33天版的Java基础视频。但我已经没时间重新都看一遍了。我当时直接开始了JavaWeb的学习,学到JDBC后发现基础实在太差,学不下去。又回过头学习了刘意老师的JavaSE视频。
我觉得如果选择一家培训机构的视频,就看他们全套的。因为知识点安排和讲课风格会大体接近,比较熟悉。当你发现视频讲得有点浅,说明你学的还不错。此时你想理解得更深的话,不要再找视频了,视频都是给初学者的,点到即止(不论哪家的视频)。直接去看书,《Java编程思想》保证够深。但还是忍住,先往后学JavaWeb吧!
毕老师30天的视频最后有简单地讲解HTML CSS JavaScript和DOM,可以给我们一个基本概念。崔老师的JavaWeb刚开始也会讲,而且更全面更详细。
前端三剑客,对于我们零基础,只看毕老师的视频是根本没法一次掌握的,但毕老师讲解后有了大概框架后,再看JavaWeb中的前端视频会吸收得更好。
建议学完HTML就马上做一个小页面,巩固下标签的知识。HTML是三剑客里最基础的,必须掌握常用的标签。
这里是我写的黄色网页代码,仅供参考:
【前端部分】
>>首先,学习html和css后记得做一个小案例,快速熟悉标签使用。
>>学习JavaScript的dom操作时,留个心眼,多关注。js的dom学好了,对后面学习xml的dom会有帮助。当然,重点是xml的dom操作。dom4j重点练习。试着自己封装一个小工具。
>>JavaWeb的反射就当复习,好好学。
【JavaWeb核心技术】
>>tomcat一定要跟着视频配置一遍。光看视频是记不住的!!
>>Http协议和servlet超级重要,多看几遍,看一遍我敢打赌你会晕。东西太多了。建议做一下思维导图,理清知识点。
>>request和response超级重要,也很难。多看几遍,不要心急。request域超级重要。
>>cookie、session、JSP超级重要。多看几遍,不要心急。session域超级重要。
JavaWeb总共四大域对象,都是很重要的。
>>day12-13,老实说,我只记得${EL表达式},知道怎么导入JSTL标签库<%@...>和核心库的使用。其他的都忘了。
>>day14一定要跟着敲,因为后面的小案例都是在这个上面扩展。这个不敲,后面的敲不了!
>>day15-19算一个小周期。都是数据库操作。还是那句话,跟着敲,才记得住。不敲你肯定记不住,真的。day-17-18-19jdbc的内容是崔老师视频的第一个精华!!其他视频难以超越的讲解!!搞清楚TxQueryRunner的编写思想对后面学习框架和框架如何实现事务有四两拨千斤的功效!
相比servlet,感觉监听器和过滤不是很重要,老师有点一带而过的感觉。
上传下载和JavaMail挺复杂的。我反正第一次没掌握,用到查吧...但这些后面的项目会用到。
>>AJAX,很难。但听说现在和json一起用的越来越多。
>>综合练习,一定要敲,即使你觉得很难,也要硬着头皮敲完。敲完以后,自信心暴涨,那时你自己对JavaWeb那些知识点是重要的哪些是次要就会有自己的理解。重要的知识点,在你心里沉淀出来。就是这么神奇!!
>>最后的基础加强,崔老师视频的第二个精华!!收获也很大。直接提升到另一个境界。为学习框架做铺垫。也算崔老师的道别礼物。
学习路线建议(按传智播客黑马程序员来)
1,JavaSE(建议三个月):
毕向东任意版(启蒙或辅助)
小白人生导师,强烈推荐,两遍
刘意JavaSE(深入浅出精华版,主看这个)
2014年年底录制,和后面Javaweb比较配,两遍
毕向东JavaSE25天版由于有点老了,整个解说都没用eclipse,不利于小白掌握eclipse使用。但内容真心不错很照顾初学者。我自己初学Java看的是25天版本,后来又看了刘意老师的。毕老师的30天版里的多线程比25天版本讲得好,也讲了前端知识。
JavaSE小结:
主看刘意。毕向东视频作为补充,重点看他的面向对象,集合,IO,30天版多线程很不错。
2,JavaWeb(建议两个月):
崔希凡——超全面的JavaWeb视频
和刘意的JavaSE衔接比较好,同样深入浅出。day14和day24~26的项目,day17~19的JDBC以及最后两天的基础提高非常棒,强烈推荐,两遍。
唯一的遗憾是这套视频没有jQuery和bootstrap 等前端内容,需要自己另外找。jQuery可以去菜鸟教程或者w3cschool学一下就好了。或者看就业班里的。
3,ssh框架(按顺序,建议20天): 重点看Spring,Struts2和Hibernate了解思想就好,看完就忘掉!!公司基本不用了。
崔希凡Struts2 + 刘悦东就业班ssh框架 + 王泽2016ssh框架 + 王泽ssh综合项目实战
①崔希凡Struts2(衔接JavaWeb,作为过渡)
②刘悦东ssh框架(Struts2讲得不错)+ 梁桐spring
③王泽2016ssh框架(言简意赅,思路清晰) + ssh综合项目实战(最后Dao抽取不错)
崔老师的Struts2毕竟是2013年的,有点老了,会比较琐碎。最重要的是,现在Struts2都不怎用了,作为了解的话,主要看值栈和拦截器,了解思想。这部分视频主要是为了给JavaWeb看崔老师视频的朋友一个过渡。怕你们舍不得崔老师。其实其他老师框架也讲得非常好。比如刘悦东,广陵散等。看完崔Struts2,就看刘悦东的框架,hibernate重点了解思想,Struts2几个视频中他讲得最好最深。最后,有了上面的铺垫,再看王泽的ssh2016,条理非常清晰,精炼,没有一句废话。每天只有2.5小时。过一遍很快。为什么三个框架要看这么多视频?因为零基础初学者要进入框架学习其实需要适应时间。就好比广陵散(王泽)的,我一开始就是看他的,当时就想:什么东西?上来就讲一大堆配置?学习任何东西我都希望能知其然知其所以然,比较讨厌死记硬背。所以我列的视频顺序,是为了照顾初学者心理。学习任何框架一定要知道,在没有它之前,前人是怎么做的,那样做存在哪些弊端,而框架又是怎么解决的。这样学才能形自己的理解。刘悦东和崔希凡算是课程上得比较有意思的。让他们带你们入门,心里好接受些。但框架东西毕竟太多,最终还是要王泽这样精炼简洁的讲解给你们梳理一遍。最后跟着王泽的ssh项目做一遍,ssh框架也就算入门了。struts2和hibernate理解思想即可,因为不用了!!但也不要走过场。你不了解Struts2和Hibernate,你就不知道学习SpringMVC和MyBatis有什么好处,各自的优缺点是什么,因为没有对比!!
我的建议是,Struts2和Hibernate做做笔记,了解思想。不用去敲代码。把你的大脑空出来给后面的springmvc和mybatis。都学的话,会混!!
3.5,崔希凡JavaWeb(day17~19,day27~28)
Javaweb阶段你可能觉得这些内容不明觉厉,但又不知道有何用处。等你学完SSH就会发现这部分内容是真的很吊。看崔老师的JDBC能一窥框架的事务原理,基础加强讲到了如何利用注解+反射搭建山寨版的hibernate和spring。
4,SSM框架(重点中的重点)
①黑马李旭讲的mybatis和springmvc
②黑马《Springmvc、Mybatis由浅入深》
③在掌握了上面的视频内容并有自己的一些见解后再去看尚硅谷的Mybatis(最后有讲源码)
之所以先看李旭的springmvc和mybatis,原因无他,就因为他只讲重点,讲得快。总共十小时,讲完两套框架。如果你领悟力够强,理论上就成了。但绝大部分人都不可能看这么一套视频就会用sm框架。所以在看李旭的视频时,要随时记录自己的疑问,然后看燕青的视频时,带着疑问去学习。mybatis主要关注输入映射+sql配置+输出映射,了解mybatis如何解决jdbc的不足。springmvc没什么建议...自己看着办。
黑马程序员官网:黑马程序员官网|Java培训|人工智能+Python培训|PHP培训|全栈工程师培训|UI设计培训|C++培训|前端移动开发培训|Android培训|iOS培训|网络营销培训
5,学习方法:
小白自学的难点在于:1,找不到合适的资料。2,不知道学习重点。
资料我已经放这了,是个人认为最适合小白的教程。ssh框架由于现在用得不多了,我找过很多传智播客的视频,觉得讲得都不是很好。刘悦东老师讲得还挺好的,起码听起来很舒服。视频也足够新,2016年年底的,作为了解很足够了。我另外提供了崔希凡老师的Struts2视频,为了能让刚学完JavaWeb的同学习惯。至于学习方法,即使我这篇文章给出了重点,可能你们还是不会相信。所以我建议:不要想着彻底掌握一块知识点再去学下一块知识点,这样永远不可能把这一套视频学好。你应该在理解的前提下用最快的时间完整过一遍,对整体学习路线有个把握。第一次学习争取每个知识点懂个50-60%,专门搞个txt文档记录观看过程中的疑问点,从后面的内容判断前面哪些知识点是重要的,常用的。然后回过头来有重点地攻克,抓大放小。
最后,我推荐的视频都是自己用过的,对比挑出来的。尽量追求深入浅出,通俗易懂。如果你觉得没看懂,就多看几遍!!“多看几遍”是最简单朴素道理,很奏效。但是很少有人相信。
其他的跟着视频就好。前期用记事本工具,我用的是notepad++,你也可以用EditPlus。后期用MyEclipse,其实就是多了插件的eclipse。要尽快熟悉MyEclipse的各种快捷键。
后记:
2017-10-4 23:21:25更新
17年5月中旬,学完毕老师的25天教程,非常照顾小白,讲得非常生动有趣。我竟然有种看电影,很享受的感觉...但JavaSE终究太难,学完之后还是有点懵。这时阅读到林琪老师的答案,很受鼓舞。里面的视频很优质。对于迷茫的我来说犹如一剂强心剂。于是5月17晚连夜写了这个答案。后续发现刘意老师的JavaSE和崔希凡老师的JavaWeb简直神作!希望让更多像我这样的小白得到帮助。断断续续的,今天我终于学习完崔老师的JavaWeb视频了。十分感慨。又来重新编辑。希望对正在阅读此答案的你有帮助。加油。
2017-10-21 11:03:11更新
在10月4日结束JavaWeb后,经历国庆长假和迷茫(各种找资料),耽误了好多时间。网上虽然很多就业班的视频,但感觉都讲得很差。尤其Struts2,要么开头就讲各种源码根本学不下去,要么只讲死规则,一点原理都不讲。感觉讲得都不怎样。由于崔老师的JavaWeb讲得很棒,本能地想继续看他的框架视频。于是网上找了很久。最终在贴吧发现有个朋友有他的视频,但只给出了第一天和最后两天的练习视频。即使这样,崔老师Struts2第一天的讲解已经比其他Struts2视频好太多,对初学者来说非常清晰易懂。连续加了一星期QQ,终于联系上那位贴吧朋友,得到了Struts2视频。另外听说汤阳光老师的Hibernate和OA项目很不错,就连同Spring一起下载了。接下来会学习上面这些视频。不过现在SSH已经用的不多,做了解吧。时间应该更多地花在SSM,也就是Spring、SpringMVC和MyBatis上。
2018-1-6 11:31:46
已经找到工作,对比周围培训班出来的朋友,我觉得自己自学出来水平还是十分不错的(和科班当然没法比)。当然,我自己也很努力。希望真心想转行的零基础朋友,每隔一个月重新看一遍上面的帖子,我想讲的话,你可能遇到的问题,我都讲到了。因为我也是跌跌撞撞过来的,太了解零基础的痛苦了!
最后还是说一句:
零基础转行太难了。望各位三思而后行。
祝学习成功。
bravo1988:零基础Java学习路线2.0版(持续更新...)长期以来,Java一直占据TIOBE编程语言排行版第一名的位置,目前已经将第二名的C语言远远甩开了。
Java目前是全世界使用最广泛的语言,其跨平台性、面向对象、安全、多线程以及简单易用的特性,使其在诞生20多年后深受开发者的喜爱。
阿里云大学联合魔乐科技推出Java系列教程,从Java语法入门,到面向对象编程,再到高级开发应用,每个阶段还提供了在线自测,让你了解学习掌握的程度。
开始学习:Java学习路线图-阿里云大学(点击学习)
路线图:
一.Java零基础入门
本课程主要讲解JavaSE的发展历史,JDK开发环境的搭建,CLASSPATH属性作用,Java程序基本结构、基本数据类型的划分及使用、程序结构、方法的定义与使用,本课程是作为Java系列课程的初期课程,掌握本课程之后可以继续学习Java高级开发部分。
课时1:【Java摸底自测】10道题测测你的Java底子
课时2:Java简介(Java发展概述)26:42
课时3:Java简介(Java主要特点)08:55
课时4:JDK的安装与配置 09:58
课时5:第一个Java程序15:00
课时6:CLASSPATH环境属性08:26
课时7:Java程序基本概念(注释)05:24
课时8:Java程序基本概念(标识符与关键字)06:18
课时9:Java数据类型划分(数据类型划分)13:14
课时10:Java数据类型划分(整型类型)30:18
课时11:Java数据类型划分(浮点类型)09:23
课时12:Java数据类型划分(字符型)11:48
课时13:Java数据类型划分(布尔型)02:56
课时14:Java数据类型划分(初见String类)1品牌8
课时15:Java运算符(基础数学运算符)1品牌2
课时16:Java运算符(三目运算符)05:42
课时17:Java运算符(关系运算符)04:54
课时18:Java运算符(逻辑运算符)07:39
课时19:Java运算符(位运算符)16:50
课时20:程序逻辑控制(分支结构)15:11
课时21:程序逻辑控制(循环结构)10:18
课时22:程序逻辑控制(循环控制)06:07
课时23:程序逻辑控制(循环嵌套)06:27
课时24:方法的定义与使用(方法的基本定义)12:07
课时25:方法的定义与使用(方法重载)08:50
课时26:方法的定义与使用(方法递归调用)15:44
Java编程基础自测题,共20道题 限时30分钟,看看自己掌握了多少:
http://click.aliyun.com/m/38108/
二. Java面向对象开发
面向对象是Java语言之中最为重要的特征,本课程主要讲解面向对象的核心知识,并且利用大量的代码、数据结构课程深入分析Java面向对象特征。
课时1:面向对象简介 13:22
课时2:类与对象(类与对象基本定义) 09:38
课时3:类与对象(类与对象定义) 09:36
课时4:类与对象(对象内存分析) 20:13
课时5:类与对象(引用传递初次分析) 15:00
课时6:private实现封装处理 16:29
课时7:构造方法与匿名对象 23:55
课时8:【第01个代码模型】综合案例:简单Java类 12:53
课时9:数组的定义与使用(数组基本概念) 14:32
课时10:数组的定义与使用(数组引用传递) 10:40
课时11:数组的定义与使用(数组静态初始化) 06:46
课时12:数组的定义与使用(二维数组) 11:20
课时13:数组的定义与使用(数组与方法互操作) 12:42
课时14:数组的定义与使用(Java对数组的支持) 08:57
课时15:数组的定义与使用(数组案例:数组数据统计) 16:51
课时16:数组的定义与使用(数组案例:数组排序) 13:28
课时17:数组的定义与使用(数组案例:数组转置) 20:16
课时18:数组的定义与使用(数组案例:二分查找法) 13:14
课时19:数组的定义与使用(对象数组) 09:05
课时20:String类的基本特点(String类两种实例化方式) 04:48
课时21:String类的基本特点(字符串比较) 08:09
课时22:String类的基本特点(字符串为匿名对象) 06:33
课时23:String类的基本特点(String两种实例化区别) 20:37
课时24:String类的基本特点(字符串常量不可变更) 10:05
课时25:String类的常用方法(DOC文档组成) 07:18
课时26:String类的常用方法(字符串与字符数组) 11:41
课时27:String类的常用方法(字节与字符串) 05:38
课时28:String类的常用方法(字符串比较) 06:13
课时29:String类的常用方法(字符串查找) 10:57
课时30:String类的常用方法(字符串替换) 02:49
课时31:String类的常用方法(字符串拆分) 07:33
课时32:String类的常用方法(字符串截取) 03:07
课时33:String类的常用方法(字符串其它操作方法) 12:31
课时34:this关键字(this调用属性) 07:15
课时35:this关键字(this调用方法) 09:58
课时36:this关键字(表示当前对象) 06:02
课时37:引用传递进阶分析 20:54
课时38:【第02个代码模型】综合案例:对象比较 11:22
课时39:引用传递实际应用 19:12
课时40:【第03个代码模型】综合案例:数据表与简单Java类(一对多) 17:07
课时41:【第03个代码模型】综合案例:数据表与简单Java类(多对多) 20:40
课时42:【第03个代码模型】综合案例:数据表与简单Java类(角色与权限) 26:58
课时43:static关键字(static属性) 17:08
课时44:static关键字(static方法) 06:25
课时45:static关键字(分析主方法) 08:41
课时46:static关键字(static应用) 06:24
课时47:代码块(普通代码块) 04:24
课时48:代码块(构造块) 04:09
课时49:代码块(静态代码块) 05:11
课时50:内部类的定义及使用(内部类基本概念) 20:56
课时51:内部类的定义及使用(static定义内部类) 04:58
课时52:内部类的定义及使用(在方法中定义内部类) 07:01
课时53:继承的定义与使用(继承问题的引出) 06:02
课时54:继承的定义与使用(继承的实现) 06:25
课时55:继承的定义与使用(继承使用限制) 2品牌3
课时56:覆写(方法覆写) 19:36
课时57:覆写(属性覆盖) 03:23
课时58:覆写(super关键字) 09:35
课时59:综合案例:数组操作(定义Array父类) 18:17
课时60:综合案例:数组操作(SortArray排序子类) 05:15
课时61:综合案例:数组操作(ReverseArray反转子类) 03:48
课时62:final关键字 06:05
课时63:多态性 28:26
课时64:抽象类的定义与使用(抽象类基本概念) 16:39
课时65:抽象类的定义与使用(抽象类使用限制) 18:06
课时66:抽象类的定义与使用(模版设计模式) 18:58
课时67:接口的定义与使用(接口基本概念) 17:34
课时68:接口的定义与使用(接口使用限制) 22:56
课时69:接口的定义与使用(使用接口定义标准) 14:34
课时70:接口的定义与使用(工厂设计模式) 13:23
课时71:接口的定义与使用(代理设计模式) 14:41
课时72:接口的定义与使用(抽象类与接口的区别) 12:51
课时73:匿名内部类 09:25
课时74:Object类(Object类简介) 06:01
课时75:Object类(取得对象信息) 07:45
课时76:Object类(对象比较) 08:50
课时77:Object类(接收引用数据类型) 05:46
课时78:包装类(包装类简介) 09:08
课时79:包装类(装箱与拆箱) 09:46
课时80:包装类(字符串与基本数据类型转换) 10:21
课时81:包的定义及使用(包的定义) 10:19
课时82:包的定义及使用(包的导入) 13:34
课时83:包的定义及使用(系统常用包) 08:36
课时84:访问控制权限 10:45
课时85:jar命令 09:38
课时86:单例设计模式(单例设计模式) 18:04
课时87:单例设计模式(多例设计模式) 05:43
课时88:【第04个代码模型】异常的捕获与处理(观察异常带来的问题) 05:35
课时89:【第04个代码模型】异常的捕获与处理(异常处理格式) 15:16
课时90:【第04个代码模型】异常的捕获与处理(throws关键字) 08:09
课时91:【第04个代码模型】异常的捕获与处理(throw关键字) 06:17
课时92:【第04个代码模型】异常的捕获与处理(异常处理模型) 09:03
课时93:【第04个代码模型】异常的捕获与处理(RuntimeException) 06:43
课时94:【第04个代码模型】异常的捕获与处理(断言) 04:20
课时95:【第04个代码模型】异常的捕获与处理(自定义异常类) 05:35
课时96:链表(链表基本概念) 17:03
课时97:链表(链表实现结构说明) 1品牌7
课时98:链表(增加链表数据) 16:14
课时99:链表(取得链表数据个数) 04:26
课时100:链表(链表数据转换为对象数组) 14:08
课时101:链表(查询数据) 06:01
课时102:链表(根据索引取得数据) 05:24
课时103:链表(修改指定索引数据) 04:07
课时104:链表(删除数据) 12:18
课时105:【第05个代码模型】综合案例:宠物商店 19:48
Java面向对象编程基础自测题,共20道题 限时30分钟,来测一测掌握了多少:
http://click.aliyun.com/m/38109/
三. Java高级开发
当你已经熟练的掌握了面向对象中的各种概念后,是否会对这些知识是如何使用的产生浓厚的兴趣?本课程主要针对于已经掌握了JAVA核心开发技术的读者准备,讲解了JAVA多线程、常用类库、IO编程、网络编程、类集框架、JDBC等与Java实际应用有关的开发技术。
课时1:Eclipse开发工具(Eclipse简介) 18:13
课时2:Eclipse开发工具(使用JDT开发程序) 33:05
课时3:Eclipse开发工具(debug调试) 09:08
课时4:Eclipse开发工具(junit测试工具) 06:07
课时5:Java基础新特性(可变参数) 11:02
课时6:Java基础新特性(foreach输出) 04:43
课时7:Java基础新特性(静态导入) 05:38
课时8:泛型(泛型问题引出) 10:03
课时9:泛型(泛型实现) 06:55
课时10:泛型(通配符) 17:37
课时11:泛型(泛型接口) 04:48
课时12:泛型(泛型方法) 03:14
课时13:枚举(多例与枚举) 06:15
课时14:枚举(Enum类) 05:30
课时15:枚举(枚举中定义其它结构) 05:48
课时16:枚举(枚举应用) 05:24
课时17:Annotation(代码开发逻辑) 12:10
课时18:Annotation(准确覆写) 05:44
课时19:Annotation(过期声明) 04:46
课时20:Annotation(压制警告) 04:12
课时21:接口定义加强 12:14
课时22:Lambda表达式 15:33
课时23:方法引用 12:15
课时24:内建函数式接口 12:30
课时25:进程与线程 13:20
课时26:Java多线程实现(Thread类实现多线程) 21:34
课时27:Java多线程实现(Runnable接口实现多线程) 07:44
课时28:Java多线程实现(Thread与Runnable区别) 16:39
课时29:Java多线程实现(线程状态) 02:50
课时30:Java多线程实现(Callable实现多线程) 14:36
课时31:多线程常用操作方法(线程命名和取得) 13:37
课时32:多线程常用操作方法(线程休眠) 08:00
课时33:多线程常用操作方法(线程优先级) 07:25
课时34:线程的同步与死锁(同步问题引出) 11:09
课时35:线程的同步与死锁(同步处理) 11:20
课时36:线程的同步与死锁(死锁) 07:54
课时37:【第06个代码模型】综合案例:生产者与消费者(基础模型) 10:48
课时38:【第06个代码模型】综合案例:生产者与消费者(解决同步问题) 04:24
课时39:【第06个代码模型】综合案例:生产者与消费者(解决重复操作问题) 09:44
课时40:线程池(线程池概念) 08:30
课时41:线程池(线程池实现) 10:49
课时42:StringBuffer类 18:34
课时43:Runtime类 10:39
课时44:System类 12:04
课时45:对象克隆 05:48
课时46:【第07个代码模型】日期处理类(Date类) 06:07
课时47:【第07个代码模型】日期处理类(SimpleDateFormat类) 11:20
课时48:数字操作类(Math类) 08:48
课时49:数字操作类(随机数) 03:23
课时50:数字操作类(大数字操作类) 12:54
课时51:Arrays类 04:14
课时52:比较器(Comparable) 11:35
课时53:比较器(二叉树) 15:04
课时54:比较器(Comparator) 08:35
课时55:国际化程序(国际化实现原理) 09:30
课时56:国际化程序(Locale类) 06:58
课时57:国际化程序(ResourceBundle) 10:28
课时58:国际化程序(国际化程序实现) 07:45
课时59:观察者设计模式 09:21
课时60:定时器 07:15
课时61:UUID类 02:16
课时62:Base64加密处理 09:07
课时63:【第08个代码模型】ThreadLocal类 15:09
课时64:【第09个代码模型】正则表达式(正则问题引出) 08:59
课时65:【第09个代码模型】正则表达式(正则符号) 17:52
课时66:【第09个代码模型】正则表达式(String类对正则的支持) 27:53
课时67:【第09个代码模型】正则表达式(java.util.regex开发包) 10:20
课时68:File文件操作类(File类基本操作) 19:01
课时69:File文件操作类(创建目录) 06:44
课时70:File文件操作类(取得文件信息) 09:45
课时71:File文件操作类(综合案例:目录列表) 1品牌5
课时72:字节流与字符流(流操作简介) 07:07
课时73:字节流与字符流(字节输出流:OutputStream) 23:21
课时74:字节流与字符流(AutoCloseable自动关闭支持) 06:44
课时75:字节流与字符流(字节输入流:InputStream) 15:31
课时76:字节流与字符流(字符输出流:OutputStream) 04:48
课时77:字节流与字符流(字符输入流:Reader) 05:24
课时78:字节流与字符流(字节流与字符流区别) 08:35
课时79:转换流 10:28
课时80:【第10个代码模型】综合案例:文件拷贝 33:34
课时81:字符编码(常用字符编码) 05:55
课时82:字符编码(乱码产生分析) 07:17
课时83:内存操作流(内存流基本操作) 19:32
课时84:内存操作流(内存流操作) 20:36
课时85:【第11个代码模型】打印流(打印流模型) 10:32
课时86:【第11个代码模型】打印流(使用系统打印流) 11:02
课时87:【第11个代码模型】打印流(格式化文本信息) 06:08
课时88:System类对IO的支持(系统输出) 09:59
课时89:System类对IO的支持(系统输入) 15:58
课时90:BufferedReader类 12:08
课时91:【第12个代码模型】Scanner类 13:13
课时92:【第13个代码模型】对象序列化(序列化基本概念) 04:52
课时93:【第13个代码模型】对象序列化(序列化实现) 11:43
课时94:【第13个代码模型】对象序列化(transient关键字) 03:56
课时95:认识反射机制 06:14
课时96:Class类对象的三种实例化模式 09:16
课时97:【第14个代码模型】反射与工厂设计模式 18:09
课时98:反射与类操作(取得父类信息) 06:03
课时99:反射与类操作(反射调用构造) 19:12
课时100:反射与类操作(反射调用方法) 12:15
课时101:反射与类操作(反射调用成员) 19:45
课时102:【第15个代码模型】综合案例:反射与简单Java类(单级VO操作原理) 18:26
课时103:【第15个代码模型】综合案例:反射与简单Java类(单级VO设置实现) 28:23
课时104:【第15个代码模型】综合案例:反射与简单Java类(多级VO设置实现) 14:59
课时105:【第15个代码模型】综合案例:反射与简单Java类(设置各种数据类型) 35:56
课时106:【第15个代码模型】综合案例:反射与简单Java类(级联实例化对象) 06:41
课时107:ClassLoader类加载器(认识类加载器) 14:44
课时108:ClassLoader类加载器(自定义ClassLoader) 12:48
课时109:【第16个代码模型】反射与代理设计模式(基础代理设计模式) 19:49
课时110:【第16个代码模型】反射与代理设计模式(动态代理设计模式) 20:55
课时111:【第16个代码模型】反射与代理设计模式(cglib实现动态代理) 12:13
课时112:反射与Annotation(反射取得Annotation) 07:49
课时113:反射与Annotation(自定义Annotation) 08:47
课时114:反射与Annotation(Annotation与工厂设计模式) 06:43
课时115:volatile关键字 14:20
课时116:网络编程(网络编程简介) 08:15
课时117:网络编程(基本网络程序模型) 09:26
课时118:网络编程(Echo程序) 18:00
课时119:JDBC简介 08:12
课时120:连接Oracle数据库 26:06
课时121:使用Statement操作数据库(Statement接口简介) 09:29
课时122:使用Statement操作数据库(Statement执行更新操作) 09:17
课时123:使用Statement操作数据库(Statement执行查询操作) 12:42
课时124:【第17个代码模型】使用PreparedStatement操作数据库(Statement执行分析) 16:50
课时125:【第17个代码模型】使用PreparedStatement操作数据库(PreparedStatement查询案例) 11:42
课时126:批处理与事务处理(批处理) 1品牌1
课时127:批处理与事务处理(事务处理) 07:04
课时128:Java类集简介 05:56
课时129:Collection集合接口 16:09
课时130:【第18个代码模型】List集合接口(List接口简介) 10:17
课时131:【第18个代码模型】List集合接口(ArrayList子类) 07:54
课时132:【第18个代码模型】List集合接口(List与简单Java类) 06:05
课时133:【第18个代码模型】List集合接口(Vector子类) 10:09
课时134:【第18个代码模型】List集合接口(LinkedList子类) 11:23
课时135:【第19个代码模型】Set集合接口(Set接口常用子类) 09:19
课时136:【第19个代码模型】Set集合接口(集合排序说明) 08:55
课时137:【第19个代码模型】Set集合接口(重复元素判断) 13:37
课时138:【第20个代码模型】集合输出(Iterator迭代输出) 09:04
课时139:【第20个代码模型】集合输出(ListIterator双向迭代) 08:11
课时140:【第20个代码模型】集合输出(Enumeration枚举输出) 05:25
课时141:【第20个代码模型】集合输出(foreach输出) 02:52
课时142:【第21个代码模型】Map集合(Map接口概述) 09:31
课时143:【第21个代码模型】Map集合(HashMap子类) 09:36
课时144:【第21个代码模型】Map集合(Hashtable子类) 06:27
课时145:【第21个代码模型】Map集合(ConcurrentHashMap子类) 23:56
课时146:【第21个代码模型】Map集合(Map使用Iterator输出) 14:46
课时147:【第21个代码模型】Map集合(Map中的key实现说明) 04:18
课时148:【第21个代码模型】Map集合(TreeMap子类) 05:10
课时149:Stack栈 06:48
课时150:Queue队列 19:06
课时151:Properties属性操作 09:17
课时152:Collections工具类 04:29
课时153:Stream数据流(Collection接口扩充) 08:30
课时154:Stream数据流(Stream基本操作) 11:07
课时155:Stream数据流(MapReduce模型) 13:49
Java高级开发知识自测题,共10道题 http://click.aliyun.com/m/38110/
更多技术干货敬请关注云栖社区知乎机构号:阿里云云栖社区 - 知乎
分首先,享一个Java入门学习的基础知识大纲:
第一章 Java 语言简介
1.1. java 的历史渊源及发展前景
1.2. java 开发方向:java SE/java ME/java EE
第二章 开发环境搭建
2.1. JDK 与 JRE 关联与区别
2.2. 开发环境搭建
- JDK 安装
- jdk 目录结构
- path 环境变量
- classpath 环境变量
- 编辑器
- notepad++/Editpuls/UltraEdit:文本编辑器,入门推荐
- Eclipse:IDE,插件式,通用灵活,中期可用
- Inteilj Idea:IDE,功能更强大,新宠,java EE 和 java web 开发必备
2.3. 第一个程序:helloWorld.java
第三章 Java 语言基础
3.1. 基本语法
- 关键字
- 标识符
- 变量名:eg.phoneNumber
- 常量名:eg.IP_ADDRESS
- 函数名:eg.getName
- 类名:eg.Person
- 注释
- 单行注释
- 多行注释
- 文档注释
- 常量
3.2. 数据类型
- 基本数据类型:byte/short/int/long/float/double/boolean/char
- 引用类型:类 接口 数组 枚举
- 字符串:String
3.3. 基本语法
- 运算符
- 算数运算符
- 赋值运算符
- 比较运算符
- 逻辑运算符
- 位运算符
- 访问修饰符
- public(公有)
- default(默认)
- protected(保护)
- private(私有)
- 基本结构语句
- 顺序结构语句
- 选择结构语句
- if 语句
- switch 语句
- 循环结构语句
- while 循环
- do while 循环
- for 循环
- foreach 循环
- 循环控制 break/contunue
- 函数方法
- 方法基础
- 方法定义
- 方法调用
- 参数传递:
- 值传递
- 引用传递
- 变量作用域
- 全局变量
- 局部变量
- 重载方法
- 函数名称相同
- 返回值、参数类型、参数个数不完全相同
- 递归方法:
- 递归调用
- 结束条件
- 数组
- 数组基础
- 数组创建
- 元素访问
- 数组遍历
- 一维数组
- 多维数组(重点:二维数组)
- 异常
- 异常概念
- 异常处理
- try...catch
- finally
- throws
- 异常分类
- 编译时异常
- 运行时异常
- 自定义异常
第四章 Java 面向对象
4.1. 类和对象
- 类的定义
- 类的创建和使用
- 类成员的封装
- 属性
- 方法
4.2. 构造方法
- 构造方法的定义
- 构造方法的重载
- this 关键字的使用
- super 关键字的使用
4.3. 内部类
- 成员内部类
- 静态内部类
- 方法内部类
- 匿名内部类
4.4. 继承
- 继承的实现 extends
- 重写父类方法
- 抽象类 abstract class
- 接口 implments
- 抽象类和接口的区别和联系
4.5. 多态
- 多态的实现
- 对象的类型转换
4.6. 关键字
- final 关键字
- final 变量
- final 方法
- final 类
- static 关键字
- 静态变量
- 静态方法
- 静态代码块
- 应用:单例模式
第五章 Java 泛型
5.1. 泛型入门
- 编译时不检查类型的异常
- 手动实现编译时检查类型
- 使用泛型
5.2. 深入泛型
- 定义泛型接口、类
- 从泛型类派生子类
- 不存在泛型类
5.3. 类型通配符
- 类型通配符?
- 设定类型通配符的上限
- 设定类型通配符的下限
- 设定类型形参的上限
5.4. 泛型方法
- 定义泛型方法
- 泛型方法和类型通配符的区别
- 泛型方法与方法重载
5.5. 擦除和转换
5.6. 泛型与数组
第六章 - Java 集合类
6.1. 集合的分类
6.2. collection 接口
- List 接口
- ArrayList 用法及原理
- vector 用法及原理
- LinkedList 用法及原理
- Set 接口
- HashSet 用法及原理
- TreeSet 用法及原理
- LinkedHashSet 用法
6.3. Map 接口
- HashMap 用法及原理
- TreeMap 用法及原理
第七章 Java 输入输出流
7.1. 字节流
- 普通的字节流:InputStream/OutputStream
- 文件字节流:FileInputStream/FileOutputStream
- 带缓冲的字节流:BufferedInputStream/BufferedOutpuStream
7.2. 字符流
- 普通字符流:Reader/Writer
- 文件字符流:FileReadr/FileWriter
- 带缓冲的字符流:BufferedReader/BufferedWriter
- 字节转字符流:InputStreamReader/OutputStreamWriter
7.3. File 类
- 文件的创建、删除和重命名
- 文件夹的创建、重命名、删除
- 文件属性的读取
- 文件属性的设置
- 遍历文件夹
- 文件的简单读写
第八章 Java 多线程
8.1. 进程与线程的基本概念
8.2. 线程的创建
- 继承 Thread 类
- 实现 Runnable 接口
- 两种创建方式的比较
8.3. 线程的声明周期及状态转换
8.4. 线程的调度
- 线程的优先级 setPriority
- 线程的休眠 sleep
- 线程的让步 yeild
- 线程的插队 join
8.5. 线程同步
- 线程安全的概念及问题产生:原子性与可见性
- 同步代码块
- 同步方法
- 死锁问题的产生及解决
8.6. 多线程线程间通信
第九章 Java 常用 API 使用
9.1. 字符串操作
- String
- StringBuffer
- StringBuilder
9.2. 日期操作
- Date 类
- Calender 类
- DataFormat 类
9.3. 系统相关
- System 类
- RunTime 类
9.4. 正则表达式
- 创建正则表达式
- 使用正则表达式
9.5. 其它常用类
- Object 类
- Math 类
- Random 类
- BitgInteger 类
第十章 注解 Annotation
10.1. 基本注解
- 限定重写父类方法(@Override)
- 标识已过时(@Deprecated)
- 抑制编译器警告(@SuppressWarnings)
10.2. 自定义注解
- 注解定义语法
- 通过反射提取注解信息
10.3. 元注解
- @Retention
- @Target
- @Documented
- @Inherited
第十一章 类加载和反射
11.1. 类加载器
- 类加载的基本机制
- 创建并自定义类加载器
11.2. 通过反射查看类信息
- 获取 Class 对象
- 从 Class 中获取信息
- 使用反射创建并操作对象
- 创建对象
- 调用方法
- 访问属性值
- 操作数组
第十二章 Java 网络编程
12.1. 网络编程基础知识
- 网络协议 TCP/UDP
- IP 地址和端口号
12.2. UDP 通信
- 服务端 DatagramSocket
- 客户端 DatagramPacket
12.3. TCP 通信
- 服务端 ServerSocket
- 客户端 Socket
第十三章 其他
13.1. 学习查阅 JDK API 文档
13.2. 学习 java 的垃圾回收机制
13.3. 学习 java 多线程并发编程
第十四章 推荐阅读 JDK 源码
- java.lang.String
- java.lang.Integer
- java.lang.Long
- java.lang.Enum
- java.math.BigDecimal
- java.lang.ThreadLocal
- java.lang.ClassLoader & java.net.URLClassLoader
- java.util.ArrayList & java.util.LinkedList
- java.util.HashMap & java.util.LinkedHashMap & java.util.TreeMap
- java.util.HashSet & java.util.LinkedHashSet & java.util.TreeSet
再来,推荐几本参考书:
1、Java 基础入门
知名 IT 教育培训机构传智播客的教材,《Java 基础入门》从初学者的角度详细讲解
了 Java 开发中重点用到的多种技术。全书共 11 章,包括 Java 开发环境的搭建及其
运行机制、基本语法、面向对象的思想,采用典型翔实的例子、通俗易懂的语言阐述
面向对象中的抽象概念。在多线程、常用 API、集合、IO、GUI、网络编程章节中,
通过剖析案例、分析代码结构含义、解决常见问题等方式,帮助初学者培养良好的编
程习惯。最后,讲解了 Eclipse 开发工具,帮助初学者熟悉开发工具的使用。
2、Java 疯狂讲义
本书并不是一个简单的 Java 入门教材,也不是一门“闭门造车”式的 Java 读物。本
书来自笔者 6 年多的 Java 培训经历,凝聚了笔者将近 6000 小时的授课经验,总结了
上千个 Java 学员学习过程中的典型错误。 本书不在是知识点的铺陈,而是致力于将
知识点融入实际项目开发中,所以本书涉及了大量Java案例:精品QQ游戏大厅、MySQL
企业管理器、多线程、断点下载工具…希望读者通过编写这些程序找到编程的乐趣。
3、Java 核心技术·卷 1:基础知识(原书第 9 版)
《JAVA 核心技术(卷 1):基础知识(原书第 9 版)》是《Java 核心技术》的最新版,《Java
核心技术》出版以来一直畅销不衰,深受读者青睐,每个新版本都尽可能快地跟上 Java
开发工具箱发展的步伐,而且每一版都重新改写了的部分内容,以便适应 Java 的最新
特性。本版也不例外,它反遇了 Java SE6 的新特性。全书共 14 章,包括 Java 基本
的程序结构、对象与类、继承、接口与内部类、图形程序设计、事件处理、Swing 用
户界面组件、部署应用程序和 Applet、异常日志断言和调试、叙述方式深入浅出,并
包含大量示例。
4、Java 核心技术(卷 2):高级特性(原书第 9 版)
Java 技术权威指南,全面覆盖 Java 技术的高级主题,包括流与文件、XML、网络、
数据库编程、高级 Swing、高级 AWT、JavaBean 构件、安全、分布式对象、脚本、
编译与注解处理等,同时涉及本地化、国际化以及 Java SE 6 的内容。《JAVA 核心技
术卷Ⅱ:高级特征》对 Java 技术的阐述精确到位,叙述方式深入浅出,并包含大量示
例,从而帮助读者充分理解 Java 语言以及 Java 类库的相关特性。
5、Effective java 中文版(第 2 版)
本书介绍了在 Java 编程中 78 条极具实用价值的经验规则,这些经验规则涵盖了大多
数开发人员每天所面临的问题的解决方案。通过对 Java 平台设计专家所使用的技术的
全面描述,揭示了应该做什么,不应该做什么才能产生清晰、健壮和高效的代码。本
书中的每条规则都以简短、独立的小文章形式出现,并通过例子代码加以进一步说明。
本书内容全面,结构清晰,讲解详细。
6、Java 编程思想 (第 4 版)
本书共 22 章,包括操作符、控制执行流程、访问权限控制、复用类、多态、接口、
通过异常处理错误、字符串、泛型、数组、容器深入研究、JavaI/O 系统、枚举类型、
并发以及图形化用户界面等内容。这些丰富的内容,包含了 Java 语言基础语法以及高
级特性。
7、Java 多线程编程核心技术此书和《Java 并发编程实战》
相反,这本书的特点是大篇幅的代码+小篇幅的精讲解,可能这和中国人写的书比较
偏向实用主义的风格有关。本书关于线程安全、synchronized、 Reentrant、Timer
等等都用详细的代码进行了讲解,而且每个大知识点下的多个小知识点都会详细讲解
到,非常有实践价值。不过这本书的缺点就是对于 Java 并发包下的一些类像
CountDownLatch、Semphore、CyclicBarrier、Future、 Callable 等都没有讲到,
重点的 CAS 和 AQS 也没有触及,重点类的实现原理也没有提。当然,这很深入了,
在学习了这本书之后如果能再去对这些知识 进行一些学习、研究的话,你一定会慢慢
成长为一个很厉害的多线程高手。
8、深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第 2 版)
这书是国内少有的描述 JVM 虚拟机原理的书籍,最大的特点是采用作者一贯的严谨而
生动的语言,清楚地向读者描述虚拟机的机制、特性、原理以及实践,非常值得一看,
比较推荐!
最后,欢迎大家来看看牛客最近推出的新项目:
【牛客带你学编程】【Java方向】0基础小白入门培养计划!_技术交流_牛客网
先献上一张Java学习路线图:
是不是看懵了?吓晕了?
再来推荐一个Java相关的资源整理大合集:https://github.com/akullpp/awesome-java
其中包括:构建工具、数据库、框架、模板、安全、代码分析、日志、第三方库、书籍、Java 站点等等。
也有伯乐在线整理的中文版,对各个资源进行了整理:https://github.com/jobbole/awesome-java-cn
然后,就该是一些经典的书籍推荐:
Java语言本身:
入门
《Head First Java》
真正的入门书籍,轻松搞笑,可以通过玩游戏、拼图、解谜题以及一些意想不到的方式与Java交互,再也不怕“从入门到放弃”。
如果你没有学过其他语言亦或是转行到计算机行业,可以先看看这本书。这本书图文并茂条理清晰,非常容易理解,练习也足够,可以让你一口气读很久而不会觉得有什么地方遗漏或者根本没记住。而且这本书可以让你从语言基础开始一直学习到包括线程、网络与分布式程序等项目,最重要的是,你将学会如何像个面向对象开发者一样去思考。
《疯狂Java讲义》
可以算是国人原创必读经典了,同样非常适合初学者。讲解内容细致全面,系统通俗,目录划分和查找非常方便,就算完全没有基础也可以学的没有什么压力。同时这本书还考虑了Java的版本升级,非常贴心。
进阶
《Java编程思想》
这是一本所有的Java学习者都无法避开的经典之作,被誉为全球最好的Java书籍。不同水平的人读这本书也会有不同的感觉,初学Java的时候也许会觉得学的非常慢,当你编程了一段时间之后再看这本书,你就会发现,你编程中遇到的问题在这本书中有很多的体现,这时候大概就是你进阶的时候了,你读这本书也会变得比从前轻松和愉快了。编程几年之后再看这本又会是怎样的感觉呢?不妨拭目以待。
《Java核心技术》
作为与《Java编程思想》齐名的大全式图书,这本书的内容更加细致,偏重与讲解Java计数,举例说明了大量API,内容翔实、客观准确,不拖泥带水,所以相比于《Java编程思想》,更注重于实用性。而且这本书全面而且易懂,放在案旁用到的时候查一查、看一看,也是Java初学者和Java程序员的必备参考书。
《Effectice java》
谷歌首席架构师的大作,也是一本经典。介绍了在Java编程中78条极具实用价值的经验规则,揭示了应该做什么,不应该做什么才能产生清晰、健壮和高效的代码,并通过例子代码加以进一步说明,这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案。
初学者读这本书可能没有太深的体会,当你有那么一两个项目的经验,再读这本书,就会发现书中提到的某个规则就是你在很多次工作经验后总结出来的最准确的描述方式
不过,这本书的中文版翻译不太好,有能力的话可以看原版。
《Java性能权威指南》
Java性能方面可能最好的一本书。深入介绍了JIT编译器、垃圾收集算法、线程同步等复杂问题,讲解了很多应用性能分析以及优化的方法,详尽讲解了Java性能调优的相关知识,帮助读者深入理解Java平台性能的各个方面,适合所有想了解性能优化的Java程序员。
以上是一些基于Java语言本身的书籍推荐,然而,作为一名工程师,从编写可读的代码,到重构现有的代码,再到设计模式,是编码的必备法则。
重构与设计模式:
《HeadFirst 设计模式》
HeadFirst 系列的另一本书《HeadFirst 设计模式》,同样是一本非常适合入门设计模式的书籍,没有之一。这本书介绍 了23 个设计模式,同样采用场景对话、打比方的方式来讲解,巧妙地让设计模式的理论在实际应用中体现出来,淡化了抽象性。
《设计模式》
设计模式领域的开山鼻祖,必读,并且值得多读几遍。虽然其中的例子是C++写的,但也很适合Java学习者读。
《设计模式解析》
如果你觉得《设计模式》太晦涩难懂,《Head First Design Pattern》又太不技术书籍了,那么这本《设计模式解析》就非常适合你。本书每章结束时都有小结和启发性复习题,可以帮助你更好地了解自学得如何了。而且这本书只介绍了几种比较常用简单的设计模式,因而在学习过程中会很有成就感。
《重构: 改善既有代码的设计》
好的代码是重构出来的,而不是一开始就写出来的,除非你的代码不用于任何业务。本书从一个重构实例开始,用代码和实例配合讲解了各种耳熟能详的重构方法,非常到位,总之,是一本程序员必读书目,书中的示例代码都是java写的。
《代码整洁之道》
篇幅不大,但却能让人受益匪浅。书中给了很多方法与规范,遵循它们可以写出整洁的代码。如何为函数,变量,类型准确的命名,如何减少注释做到代码即文档,如何通过良好的编程规范减少错误的代码等等,这些都需要在工作学习中总结经验形成习惯。
是不是感觉,一个头两个大?
别急,还有各种教程:
Java 教程(菜鸟教程)
SQL 教程、MySQL 教程、JDBC 教程
JSP 教程(菜鸟教程)
mybatis 入门教程、Mybatis 深入浅出系列
Spring Cloud 中文官网、史上最简单的 Spring Cloud 教程
......
总之,这是一个资源极大丰富的时代,我们可以选择各种各样的学习方式。然而选择太多有时候也不是什么好事,如果不知从何开始,不妨找一些课程资源,让前辈老师带你入门,这样也可以少走一些弯路。
我们九章算法有一个《Java入门与基础算法》课,是硅谷资深Java工程师讲的,非常适合从零开始学习Java、算法与数据结构,有转专业找工作需求的小伙伴们,目前免费学习,戳这里。
九章算法,硅谷一线工程师在线直播授课,已经帮助30000+人成功拿到心仪offer。
更多课程信息请访问:九章算法
关于JAVA我已经说了很多,毕竟其他给视频给Android给什么多线程的都是错误的路线。你要不相信,你问问看多少人通过那些学习路线找到工作了呢?
学java就是学语法和API,这是十几年以来最大的误区。很多人把大把的时候浪费在JAVA语法和底层的api,甚至到jdk源码上,就是没弄明白一个问题,学JAVA是干嘛的,工作中会用到什么?
还有人会在框架上下功夫,但也就是ssh,实际上一个成熟的项目里,10几种框架是很正常的 。
还有人去学习算法,做各种面试题,刷各种竞赛,还是在拿学校里的心态谈工作。可是对大多数人而言,你要做的就是找到一份工作,你的资质和能力也没那么强,比天赋这条路适合你么?
所以最好的学习路径,一定是要自己主动去想,在工作中我需要做哪些事。
与其反复纠结说,我学JAVA怎么学,为什么不是问,工作中我需要做什么,怎么从简单的入手,一步步做到可以独立完成项目?
如果你能接受这种观点,你就可以继续做下去了。
第一步,你需要有根据业务需要设计db的能力。这一步,完全不需要JAVA语法知识,你需要的是业务理解力和mysql的相关知识,以此也可以看到,问JAVA学什么,这种学习方式一开始就限制了自己思维方式。
第二步,学会用java对db增删改查。这里是JAVA语法第一次登场,但是又直接引入了jdbc,mybatis,hibernate,spring的登场。
这第二步往往是比较困难的,你除了学习JAVA语法,熟悉IDE,弄明白main函数执行方式,搞懂各种配置文件,还需要去写单元测试。
但你可以将你需要学习的内容最小化,你完全不用管什么面向对象,什么数据类型,什么递归,什么多线程,你要做的就是增删改查。
只在用到的时候再去学,书籍和视频都是在你产生困惑的时候去查阅的资料,绝不是学习的顺序。如果你还是习惯买几本书按目录挨个啃,你就错的太离谱了。正确的学习姿势是,先翻目录,了解全貌,再看自己要做的事情中需要什么知识点,快速浏览,直接动手,从错误中学习,不断培养自己解决问题的能力,然后再重新回到课本,把知识点融汇贯通。
真正的学习都发生在解决问题的过程中。想想这和你从小到大的学习理念差别有多大?
第三步,学会部署到服务器上,跟svn,git,shell,死磕到底。
第四步,上手spring mvc,tomcat,jetty,熟悉日志,配置,内存占用,http请求这些东西。这能够让你提供api,这是最主流的开发方式,所以你还会在这个过程里学会json。
第五步是学习用jsp套页面
第六步是学会添加缓存,将tps提升到400
第七步是学习第三方API,短信,图片。
第八步是学会rmi,拆离服务,弄懂分布式。
你以为这就算完事了么?
不不不,还差很多。嗯,手机打字很久了,以后有心情再说。
打个好基础
任何语言学习都可以分成两部分:语言基础和具体开发。
语言基础就是变量,函数,基本面向对象,各种语法。
具体开发就是语言在具体领域的应用,这个领域的开发环境,特定的库,领域概念,开发实践等。
Java的语言基础掌握起来并不难,可以借助网络资料如:
- Codecademy
书本如:
- Java语言程序设计:基础篇
也可以借助在线课程,如:
- Java入门
- 从零开始学Java
- 成为专业Java工程师
熟悉语言基础的关键,不在于看书看视频本身,而在于看了书和视频是否动手。
动手的途径很多,可以:
- 本机环境练习
- 用网上模拟环境练习
我建议你尽量用本机真实java环境练习,因为模拟环境未必能模拟出真实编译环境的各种问题。
尽量保证自己能有至少100个小时的基础语法训练,才能形成基本的肌肉记忆。
我建议你把练习代码版本控制起来,不要扔掉,给自己留个底,回头看看有一定作用,看老代码产生新想法很常见。你可以把练习代码放到github上,如果有人要看会很方便,也会给你自己找到一点流程的感觉。
要慢下来,如果过快,基础不打牢固,后面的高级技能学起来会很不顺手。
资料不是越多越好,而是要适合;学基础不是越快越好,而是要“主动”放慢速度。
学习的一般规律是先慢后快,到后面速度会越来越快。
语法的学习最好全面一点,有的语法简单,很好上手,有的语法比较高级,背后有复杂的概念,也要学,也许不需要一下子全部记住,但要有印象,这样用资料的时候不至于碰到完全陌生的代码。
心态和预期
学习一定会碰到问题,犯错误,尤其初学。对待问题和错误的心态很重要,直接决定学习效果。
错误的心态有几种:
- 觉得自己是“知道”的,所以就放过去的
- 觉得错误是不“应该”的
- 碰到就躲,嫌麻烦
如果学习不和问题错误打交道,只拣好啃的骨头啃,那还学什么?学习过程中最有价值的地方,就是你碰到的问题,所犯的错误,用资料用个表面,学一点“容易”的东西,谁不会呢?
问题和错误一个个解决过去,解决一次很可能以后就不用再解决了,这就是“经验积累”。
所以学习者应该有形态要对:
- 问题和错误是“正常”的,“必要”的
- 问题和错误是“机会”
- 今天解决,以后就轻松了
我建议你养成一个搜集错误的习惯,不需要很复杂,记一笔,放到一个地方就可以了,不需要记很多,解决一个删除一个,这个问题和错误清单能够帮助你集中注意力。
在具体开发中学习
过了语言基础这一关,你应该进入具体开发(边开发边学习),注意,开发在前,开发就是最好的学习,这个过程你会碰到更多问题,犯更多错误,什么是正确的心态,我前面已经说了,不再赘述。
Java的主要应用领域:
- web 开发
- Android 移动开发
- 大数据处理
其他地方也有应用,但时间关系我就不列了,你可以到拉勾网找java的职位,自己分析哪些领域在用java。
在你用具体开发资料之前,要选一个方向,不要什么都学,不要贪,要做决定,要选择。
每个具体领域的开发所需要的领域知识都不同,用到的库都不同,开发流程也可能有微妙区别,同时学的后果就是互相干扰,会让你信息过载。
当你进入java web开发的时候,你会同时学web开发的领域知识(domain knowedge),还会学很具体的技术栈,可以是框架,库,或其他web开发用到的技术。Android移动开发和大数据处理也一样。
你学习语言基础的目的之一,就是能更好的学习和运用这些库,能把领域内的概念和实现用Java表达出来,你现在在“用“Java而不是“学”Java。
这个阶段,我觉得视频比较好,有几个优点:
- 新,相比很多书,视频课程更新
- 多媒体学习本身的优势,有声音,有图像演示,信息量大而且传播快
无论是书,还是在线课程只是工具,你榨取信息的工具。
榨取信息的目的是运用,运用起来你的学习进度条才会往前走,明白这一点至关重要。
下面我推荐几个Java各个主流开发领域你可以用的视频课。
Web(后台)开发:
- Java, JSP和JDBC入门开发
- Spring框架轻松起步
- JSP, Servlets和JDBC基础,开发数据库应用
- 给初学者的Spring和Hibernate
- Spring Boot,掌握Hibernate和JPA
Android 移动开发:
- Android O & Java开发移动应用
- Android Oreo开发23个应用
- Android N开发教程
大数据:
- 这个领域正在快速被Scala取代,所以就不推荐了
使用具体开发的课程要注意两点:
- 有的课程会先教语言基础,你可以选择性略过,也可以温习一遍
- 课程并不需要多,一个领域最多用两门课,资料不是越多越好
- 尽量不要碰“最新技术”,而要去学“最成熟技术”,成熟技术才是好投资
精通
具体开发所花的时间,不能少于三个月,你可以做一个大项目,你可以做多个小项目,但绝对时间必须保证,否则你会立刻成为那种半吊子。
在这之前不要去求职,你的简历上还没有任何有价值的东西可写。
有价值的东西,是指你通过这个过程所写的所有东西,尤其是项目和代码。
你应该读一读:
- 怎样才算学完一门在线课程
- 把专业带向纵深
- MOOC 学习辍学原因?
在具体项目的开发中(哪怕你是边开发边学习),你会“意识”到高级概念和实践的重要性,如设计模式,内存管理,高级语言功能,多线程,甚至数据结构与算法等等,当你有这个意识的时候,你的水平正大踏步往“专业”开发走去,这是开发中最难的部分,你可以有选择地使用一些课程:
- Java大师教程:掌握设计模式
- Java集合与泛型
- Java 9:数据结构与算法高级教程
- Java内存管理
- Java多线程与并发编程
当你想往简历上写“精通”的时候,指的是这些东西,因为基础和基本运用是无所谓“精通”的。
你在学习语言基础的时候,很可能对这些东西有过映像,现在在具体开发中,你意识到了他们的实际“意义”。
这些高级技能,用视频教程的好处是能更直观地理解,坏处是往往视频教程讲不到特别深,你可以考虑配合书本,我就不列了,你可以自己去找,自己研究下去。
进入市场
你已经写了很多很多东西,对Java整个栈,对你选定的领域,已经充分了解,现在你缺的就是一份工作,成为Java开发工程师,你能在招聘网站找到很多工作。
但面试和求职是一个需要准备的过程,学好Java不完全等于你能驾驭Java开发工程师的面试,求职是一项重要的非技术技能:
- 获得你理想中的Java工作:中级面试
此时你已经不需要初级面试题(如果你之前没有偷懒),你现在还做不了高级Java职位,因为你刚开始,而且高级面试题不在纸上,而是要用你几年的经验来回答的那些。
学习是一个循序渐进的过程,是一件非常难得坚持的事情。如果真的想学Java,一定要下定决心!
这里我分享给你的Java学习线路图,希望对你有帮助:java学习线路图
这个学习线路图我分为了几个阶段,每个阶段能学到什么,能做什么,具体知识点请往下看,每个阶段知识点我都整理出来了,更适合学习!
java语言入门
可掌握的核心能力:
掌握Java开发环境基本配置;
掌握运算符、表达式、流程控制语句、数组等的使用;
熟练使用Idea开发工具;
掌握Java基本面向对象知识;
掌握常用类String、ArrayList等的使用。
配套视频:
毕向东Java基础教程(适合初学者入门的Java基础视频)资料资料:http://pan.baidu.com/s/1nvODtSP 密码:h52i
java语言进阶
可掌握的核心能力:
深入理解Java面向对象相关知识点;
掌握开发中常用类如集合、IO流、时间日期等操作;
掌握Java异常处理机制,熟悉Java多线程开发;
掌握网络基础知识,了解Socket原理,TCP、UDP协议;
掌握java基本语法完成单机程序的编写;
熟悉Java新特性,如Lambda、Stream流等操作
配套视频:
Java快速入门教程(Java基础班全套教程)链接:https://pan.baidu.com/s/1o9yLBsu 密码:wwd0
Javaweb
可掌握的核心能力:
掌握Java JDBC、连接池操作,熟练操作mysql数据库;
熟悉web开发中常用知识如 HTML5、CSS3、JavaScript、BootStrap、jQuery等;
掌握JavaWeb开发核心技术 Servlet、Listener、Filter等;
熟悉Linux服务器,并安装开发常用软件tomcat、mysql、nginx等;
掌握同步及异步操作的JavaWeb开发,具备B/S结构软件开发能力,完成基本的JavaWeb项目;
熟悉基本的项目管理工具Maven的使用。
配套视频:
JavaWeb教程_JavaWeb入门教程|黑马程序员资料:http://pan.baidu.com/s/1bp02SFX 密码:2xfl
项目一
可掌握的核心能力:
掌握企业中最常用SSM框架开发,开发出结构清晰、可复用性好、维护方便的企业级应用程序;
掌握AngularJS框架;
掌握Spring security框架;
掌握dubbox分布式调用技术;
掌握zookeeper分布式应用协调服务;
掌握Freemarker模板引擎;
掌握全文检索解决方案;
掌握spring boot1.x框架的基本应用;
掌握CAS实现单点登录;
掌握CORS实现跨域;
掌握微信扫码支付;
掌握电商秒杀解决方案;
掌握SpringTask实现任务调度;
掌握MavenProfilel实现开发与生产环境切换;
了解电商开发中相关业务模块如商品、订单基本操作;
了解电商开发中相关术语SPU和SKU等;
积累互联网电商项目开发经验。
配套视频:
Java教程|Springmvc由浅入深教程资料:http://pan.baidu.com/s/1bpBwMfX 密码:4dpt
Java教程|Mybatis由浅入深教程资料:https://pan.baidu.com/s/1pKFaqTH 密码:w00x
Maven教程_Maven视频教程|黑马程序员资料资料:http://pan.baidu.com/s/1kVsl04v 密码:j5h0
项目二
可掌握的核心能力:
熟悉基本的Java爬虫开发,掌握webmagic爬虫框架使用;
掌握httpClient的使用;
掌握spring data jpa框架;
掌握Spring boot2.x框架;
掌握Spring Cloud框架;
掌握MongoDB数据库使用;
掌握RabbitMQ消息中间件使用;
掌握Elasticsearch分布式搜索引擎;
掌握Rancher实现容器部署管理;
掌握Grafana实现服务的实时监控;
熟悉NodeJs环境,使用Npm和cnpm管理包资源;
熟悉ESlint进行前端语法校验;
熟悉axios的使用;
掌握vuejs框架的基本使用;
掌握瀑布流组件使用;
掌握前端页面分享功能的实现;
掌握企业级DevOps解决方案,熟悉Docker、Jenkins、git等;
了解spark mllib als 机器学习算法库实现智能分类;
了解DL4J深度学习框架实现智能推荐。
配套视频
2018年Vue.js深入浅出教程链接:https://pan.baidu.com/s/1Uwja4t4ZE7cmm-l0xufkFg 密码:8v9c
深度掌握Springboot实践技术教程微服务初级课程
配套视频
SpringBoot教程_SpringBoot视频教程|黑马程序员资料: http://pan.baidu.com/s/1eR15iWa 密码: 3gcz
微服务高级课程
可掌握的核心能力:
ServiceComb改造十次方项目;
了解Kubernetes作用及为什么使用Kubernetes;
会使用K8S API完成基本操作;
理解微服务引擎CSE的功能;
能够实现ServiceComb项目接入CSE;
能够实现学成在线项目接入CSE;
理解云容器引擎CCE的功能;
能够使用容器镜像服务上传镜像;
能够将学成在线微服务部署到CCE;
能够测试微服务治理常用策略;
能够理解Mesher的作用;
能够完成学成在线使用Mesher接入CSE。
视频未更新,更新后上传
框架架构高级
可掌握的核心能力:
能够理解ORM框架;
使用Socket进行系统之间通信;
掌握在Java中开启多线程的三种方式;
掌握使用Netty实现通信;
掌握Netty常用的传输方式及ByteBuff的使用方法;
理解及时通信框架的架构;
掌握Protobuf数据格式及在Java中应用Protobuf;
掌握使用Netty实现服务端、客户端;
理解虚拟机client与Server的运行模式;
学习垃圾回收的算法;
掌握jps、jstat、jinfo、jstack、hprof等命令的使用;
掌握图形化监控工具JConsole工具的使用;
掌握Mission Control虚拟机诊断工具的使用;
掌握压力测试工具JMeter的使用;
掌握调整参数测试Tomcat的性能;
掌握“双亲模式”的原理以及解决方案。
好客租房项目
可掌握的核心能力:
能够实现房源信息更新的通知;
实现用户信息、房东、审核等功能;
能够实现API文档与模拟数据接口开发;
能够实现收藏、分享、举报、联系房东、预约看房、在线签约功能;
掌握微信小程序开发;
实现日志数据的清理以及推荐。
大数据转型Hadoop3
资料链接:https://pan.baidu.com/s/1smCTwRj 密码:vp5v
目前有几个阶段还未有视频更新,有视频了我会继续上传哦!如果有特别想要我放出的视频,也可以留言哒!
松松手指,准备开场。
说到Java,基本上可以分成以下阶段的学习(适合于完全零基础的非计算机专业科班生):
第一阶段:对DB的增删改查。
第二阶段:提供Json数据和会用Jsp套页面。
第三阶段:调用第三方API:支付,IM,图片等,以及定时任务等。
第四阶段:缓存
第五阶段:分布式
第六阶段:消息队列
第七阶段:NOSQL数据库
第八阶段:ElasticSearch和Scrpay(Python语言做为附属工具登场)
第九阶段:DEVOPS
这其中伴随着Java语法的学习,数据库的学习,Spring的学习和各种源码的原理的学习。
还包括各种业务逻辑,DB表结构的设计,性能优化,架构设计。
嗯。还有Shell,Python,Go,Groovy。
这九个阶段,足以让你走到年薪30万的级别了。
其他的想说,又懒得说了。
Java技能树
http://weixin.qq.com/r/SjmhubTEyum1rfDa92xY (二维码自动识别)
全网最详细【Java学习路线】,称霸职场,挑战20万~35万年薪!
新手该如何一步步的学习 Java?
如果真的想学Java,最好要循序渐进,有章有法的学习它!
今天小慕就不说一些学习方法和技巧了,直接来谈每个阶段要学习的内容。
首先,给大家分享一张以 企业岗位需求为导向 Java工程师技能点图
根据 Java工程师技能点图,我们分为四个阶段:
第一阶段 :Java基础
- Java基础语法学习知识
- Java中的main()方法详解
- Java中的运算符
- Java中的数组
- Java中List与数组互相转化
- Java 学习之集合类(Collections)
- Java基础之多线程没那么复杂!
- Java线程池相关知识点总结
- Java基本数据类型与包装类、字符串之间的转换
- Java 学生成绩管理(数组,嵌套循环,冒泡排序,表格输出四块融合)
- 来谈谈JAVA面向对象 - 鲁班即将五杀,大乔送他回家??
- Java类的继承与多态
- Java泛型总结——吃透泛型开发
第一阶段配套的视频教程
- Java零基础入门 | 课程总时长:40小时,27门课
教学目标:掌握必备Java语法基础,理解面向对象开发思想,学会使用常见
Java API,能够简单快捷完成常用代码逻辑开发。
第二阶段 :Java Web
- Java Web从前端到后台常用框架介绍
- JAVA遇上HTML-----JSP 篇
- 总结 Java 内部类的一些使用与梳理
- Java Web开发网页篇—表单
- Java Web开发网页篇—开始使用MyEclipse
- 聊聊java过滤器是怎样使用的?
- Java正则表达式的语法与示例
- Java Web开发—Servlet是干嘛的
- Java Web开发—Servlet篇之get与post
- Java Web开发—Servlet篇之内置对象
- Java Web开发——Java篇—从内存讲起
- Java开发必会的Linux命令
- 使用Gradle构建eclipse Java web项目
第二阶段配套的视频教程
- 从网页搭建入门Java Web | 课程时长38小时,28门课
教学目标:从网页搭建开始入手,通过大量实际开发案例来掌握Java Web
础,最后能使用MVC模型进行项目开发,逐步深入完成Java
Web小白的蜕变!
第三阶段 :数据库开发与设计模式
- Java框架篇—Mybatis 入门
- 如何优雅的使用mybatis
- SpringMVC+mybatis配置详解
- Mybatis常见面试题
- 如何学好,用好MySQL数据库?
- Java------JDBC连接MySQL数据库
- Java连接mysql数据库的两种途径:JDBC和连接池
- Java 反射机制的应用实例
- 项目管理工具——maven实战笔记
- Spring MVC + MongoDB + Maven搭建项目开发环境
- Java设计模式----------抽象工厂模式
- Java设计模式——单例模式
第三阶段配套的视频教程
- Java数据库开发与实战应用,课程时长25小时,12门课
教学目标:从流行的MySQL数据库开始,到Java原生的数据库应用程序接口
JDBC的使用,再到常用的数据持久化框架MyBatis,完成数据库
项目开发,实现页面数据的增删改查。
第四阶段 :SSM主流框架
- Java中String的用法总结
- 死磕Spring源码-AOP分析
- 从Java基础开始学习Spring AOP——Java方法反射
- 从Java基础学习Spring AOP——JDK动态代理(重点内容)
- SpringMVC从入门到精通之第一章
- SpringMVC从入门到精通之第二章
- SpringMVC从入门到精通之第三章
- java–最新SSM框架整合日记(上篇)
- java–最新SSM框架整合日记(下篇)
- springboot(一):入门篇
- springboot整合shiro-登录认证和权限管理
- 腾讯云SpringBoot部署 + HTTPS配置
- Spring boot + mybatis + Vue.js + ElementUI 实现数据的增删改查
- SpringMVC+Spring+Mybatis整合程序之整合
第四阶段配套的视频教程
- SSM主流框架入门与综合项目实战 | 课程时长35小时,19门课
教学目标:实际开发中非常流行的Spring、SpringMVC和MyBatis三大框
架,并用这三大框架进行整合开发 ,还原真实开发场景,让你高
效独立地完成项目开发,真正达到企业用人水平。
最后
以上四个阶段,只要每天学习2小时,轻松让你从Java入门到入职,
实现你的就业梦,还有20万~35万年薪等你拿!
想要学习全套Java视频学习的小伙伴,移步到 Java攻城狮就业课程
当你顺利完成了Java就业路线,欢迎勇闯慕课网Java实战,突破你的技术瓶颈,成为一枚更更更优秀的Java人才。毕竟开发这条路途,无论你工作多久,都会遇到各种奇奇怪怪的问题,以及形形色色的bug等着你去解决!
最后,如果觉得此文对你有所帮助,请收藏+点赞吧!
学习java贵在坚持,更要有目标,下面分享给你的这个学习路线图是2019年最新的学习路线图。
这个学习线路图我分为了几个阶段,每个阶段能学到什么,能做什么,具体知识点请往下看,每个阶段知识点我都整理出来了,更适合学习!
基础篇
1.java基础入门
本套java基础入门教程包含四个重点知识点,全套免费视频教程。
知识点:
环境搭建:(重点掌握)
常用DOS命令及快捷键、EditPlus的安装、通用文本编辑快捷键、安装JDK、第一个Java程序的开发、Java注释、public class和class的区别。
基础语法:(重点与理解)
重点:变量、方法初步、运算符、数据类型、控制语句。
理解:标识符、关键字、字面量、方法重载/overload、方法执行是的内存变化、package与import。(方法重载/overload、方法递归、package与import里也包含重点)
IntelliJ IDEA工具的使用(重点)
数组初步:(重点与理解)
重点:一堆数组、可变长参数、二堆数组。
理解:数组数据结构详解、算法。
十一天阶段练习题
网盘链接:
链接:https://pan.baidu.com/s/1vf4ktCOO96_CTgnPInBCSg
提取码:u6ll
2.javase
本套javaSE进阶视频教程包含八个知识点,全套视频教程免费
面向对象:(重点)
类的定义、对象的创建和使用、构造方法、当实例变量是一个引用的时候、封装性、this关键字、方法调用时参数的传递、空指针异常、累的继承、多态、final关键字、内部类......
数组高级特性:(重点)
数组拷贝及扩容、数组工具类Arrays的应用。
常用类:(重点及理解)
重点:
String、StringBuilder StringBuffer、Integer、Date。
掌握:
BigDecimal、枚举类型、随机数Random
集合:(重点及理解)
重点:
UML演示Collection继承结构图、Collection接口常用方法、Collection的通用迭代、UML演示Map继承结构图、Map接口中常用方法、Hashtable集合的子类Properties、TreeMap集合、泛型、Collections集合工具类。
理解:
集合概述、List集合、HashMap集合、HashMap、Hashtable、ConcurrentHashMap的区别、增强for循环。
反射机制:(重点及理解)
重点:
获取Class的三种方式、通过反射机制调用无参数构造方法创建对象、类加载。
理解:
通过反射机制访问对象的Field、通过反射机制调用对象的Method。
Annotation:(重点及理解)
重点:
JDK内置注解:@Override、总结注解在开发中有什么作用。
理解:
自定义注解、反射机制读取注解。
异常:(重点及理解)
重点:
异常继承结构图、处理异常、finally语句块、final、finalize、finally有什么区别、异常在实际开发中的作用。
理解:
异常概述、方法覆盖与异常。
Java新特性:(重点及理解)
Java7特性重点:
switch支持String、泛型自动类型推断
理解:可catch多个异常,异常之间使用“|”分隔
Java8特性重点:Lambda表达式、接口中的默认方法和静态方法、新的Date API。
网盘链接:
链接:https://pan.baidu.com/s/1DDIOPPw7sg875IlhugszhQ
提取码:gdgs
javaweb前端
本套Web前端的知识点包含六个部分
javaSE:(重点及理解)
重点:
IO流、多线程以及线程的同步面试题。
理解:
NIO、网络编程。
MySQL:(重点及理解)
重点:
登录MySQL、基本命令、初始化测试数据、简单查询、条件查询、排序操作、分组函数、分组查询、单表DQL总结、链接查询、子查询、union&union all、limit、表、事务、视图、DBA命令、数据库设计三范式、34道SQL作业题。
理解:
MySQL安装与完美卸载、DBMS、SQL、DB、表的概述、SQL的分类、常用命令、数据处理函数、存储引擎、索引。
JDBC:(重点及理解)
重点:
JDBC编程六步、使用Statement完成增删改、连接数据库的信息在属性资源文件中配置、安装PowerDesigner工具,设计用户表、Statement和PreparedStatement区别、PreparedStatement演示增删改、PreparedStatement演示模糊查询、JDBC事务、悲观锁for update和for update nowait、java.util.Date和java.sql.Date的区别与相互转换、封装DBUtil工具类。
理解:
接口在开发中的作用、驱动配置、Statement演示登录时的SQL注入问题、PreparedStatement解决SQL注入。
HTML:(重点及链接)
重点:
第一个HTML、实体符号、表格、图片、超链接、列表、表单、HTML中元素的id属性、div和span。
理解:
HTML概述、基本标签、背景颜色和背景图片。
CSS:(重点及理解)
重点:
HTML中嵌入CSS样式的三种方式、边框、隐藏、字体、文本装饰、列表、设置鼠标悬停效果、内边距和外边距、布局float、定位、鼠标小手。
理解:
CSS的理解。
JavaScript:(重点及理解)
重点:
嵌入JS三种方式以及JS的注释、变量、null NaN undefined区别、JS中的事件、JS运算符之void、JS内置对象、DOM编程案例、BOM编程案例、JSON对象、总结一下浏览器向服务器发送请求的常见方式。
理解:
JavaScript概述、JavaScript包括三块:ECMAScript、DOM、BOM、标识符和关键字、JS数据类型(ES6版本之前的数据类型有6种 重点)、JS之控制语句、BOM和DOM的区别与联系。
网盘链接:
链接:https://pan.baidu.com/s/1BKhxkTD5aXdwAHJB89I4IQ
提取码:76xr
JavaWeb:
本阶段视频教程包含八个知识点——全套视频教程免费
XML:(重点及理解)
重点:
XML概述:(XML在实际开发中的作用、XML和JSON的对比)、Java解析XML:(dom4j+xpath解析XML)
理解:
XML概述、XML解析、Java解析XML
Servlet:(重点及理解)
重点:
tomcat服务器安装与配置、开发第一个Servlet程序、单实例多线程环境下运行的Servlet、HTTP协议详解、ServletContext、HttpServletRequest、HttpServletResponse、web开发中乱码的解决方案、Cookie、HttpSession、转发与重定向、Filter、案例
理解:
系统结构概论、Servlet对象生命周期、GenericServlet、HttpServlet、ServletConfig、Listener、Servlet3.0新特性
JSP:重点
重点:
JSP基础语法、EL表达式、JSTL标签、案例。
Maven:(重点及理解)
重点:
Maven的安装与配置、第一个Maven工程、IntelliJ IDEA中使用Maven、修改本地仓库的路径、Maven的插件。
理解:
Maven概述、Maven基础知识
MVC机构模式:(重点及理解)
重点:
MVC架构模式和三层架构(表示层、业务层、持久层)或多层架构的区别与联系、案例3:改造案例2,改造之前的DBUtil工具类,将Connection对象放到ThreadLocal当中,在service层控制事务和关闭Connection对象,关闭Connection时将它从ThreadLocal中移除、GoF之代理模式:动态代理(JDK动态代理)、案例4:改造案例3,使用动态代理模式处理service层事务。
理解:
案例1:不使用MVC架构模式开发账户转账功能,分析缺点、MVC架构模式的分层理论、案例2:使用MVC架构模式改造案例1,总结优点、GoF之代理模式:静态代理。
AJAX:(重点及理解)
重点:
AJAX发送get请求、AJAX的get请求缓存解决方案、AJAX发送post请求、AJAX什么情况下使用同步方式
理解:
AJAX概述、AJAX实现原理(异步通信原理)
jQuery:(重点及理解)
重点:
jQuery概述、我的第一个jQuery程序、DOM对象与jQuery对象、jQuery的事件处理、jQuery九大选择器、jQuery对象的常用方法、jQuery元素的遍历、jQuery发送AJAX请求、AJAX跨域、未来新增元素的事件绑定
理解:
jQuery动画
综合案例(重点):使用Servlet+JSP+MVC+AJAX+jQuery+Maven完成单表数据维护
网盘链接:
链接:https://pan.baidu.com/s/1Or0_Lyl7TxyzmVqV9wqf8A
提取码:qdpd
JavaWeb项目:
本阶段视频教程包含六个知识点——全套视频教程免费
MyBatis:(重点及理解)
重点:
开发第一个MyBatis程序、MyBatis集成log4j打印日志信息、实现insert操作并演示MyBatis的事务机制、使用单独的属性资源文件配置连接数据库的信息、sqlMapper配置文件中namespace的作用、MyBatis的别名机制、MyBatis完成单表selectList操作、MyBatis完成update操作、MyBatis完成delete操作、作用域(Scope)和生命周期、在WEB应用的持久层DAO中使用MyBatis、MyBatis使用动态代理机制生成DAO接口的实现类、SqlMapper配置文件采用package的方式扫描、MyBatis的别名机制采用package的方式、parameterType详解、多参数传递、resultType详解、resultMap基本应用、#{}和${}的区别及选用。
理解:
MyBatis概述、resultMap高级应用、MyBatis的延迟加载机制、动态SQL、一级缓存和二级缓存、MyBatis-Plus、Mybatis通用Mapper、MyBatis分页插件PageHelper。
GIT:(重点及理解)
重点:
安装Git、Git版本库、时光机穿梭、远程仓库、分支管理、标签管理、使用GitHub、使用码云、搭建Git服务器、IDEA集成Git、IDEA中使用Git。
理解:
Git概述。
BootStrap:(重点及理解)
重点:
下载Bootstrap库、第一个Bootstrap程序、完成Bootstrap案例。
理解:
Bootstrap概述、常见的前端UI框架有哪些、JS、jQuery、Bootstrap的区别与联系、要实现的Bootstrap案例效果展示。
CRM:(重点)
重点:
软件开发生命周期、CRM核心业务介绍、CRM核心功能实现。
Linux:(重点及理解)
重点:
Linux常用命令、发布web项目到Linux。
理解:
Linux操作系统概述、安装虚拟机vmware、在虚拟机上安装Linux操作系统CentOS7、CentOS7操作系统目录介绍、常见操作Linux的远程工具包括哪些、远程工具。
网盘链接:
链接:https://pan.baidu.com/s/1ifKuxTH8S4vsfm-Ram793g
提取码:w0oo
视频教程也在持续更新,配套教程完整版请移步:
自学经典《java视频教程》全套免费下载的基础到就业java教程推荐阅读:
全网最全Java基础视频教程-知乎专栏
关于答主:985、通信、A+学科硕士,2018年的秋招收获了:百度、腾讯、头条、美团、猿辅导、度小满、猫眼、流利说等offer。秋招之后,申请了一个微信公众号【菜鸟名企梦】,初衷是把自己的求职期间的总结、经验分享给后来的找工作的学弟学妹们,让后来求职找工作的学弟学妹们少走弯路。公众号主要是【java】【大数据】【互联网求职面试】相关技术分享。
所有抛开求职就业目标、不切实际的学习路线都是耍流氓。文章主要主要介绍了:答主以及身边同学的学习经历,从准备秋招,倒推学习路线,具有很强的操作性。
文章将会系统全面介绍整个秋招准备流程以及注意事项,这篇文章不需要读者有任何的编程语言基础,本文会从战术和战略层面教你如何备战秋招,从秋招倒推学习路线,以下是正文,文章主要由以下几部分组成:
第一阶段:基础和自我定位
- 求职定位:自我认知:找那个方向的工作
- 4T全套学习资料分享:学习资料
- 零基础-java学习路线:怎么学?
第二阶段:求职面试技巧
- 求职项目相关:如何准备面试中的项目相关问题
- 关于实习:实习的优势与劣势?要不要找实习?
- 算法:如何备考面试中的算法部分?
- 面经:面经相对于真题,如何获取高质量面经?
- 面试书籍推荐:查漏补缺,经典必看技术书籍?
- 如何撰写简历:简历注意事项?
- 答主珍藏的优质学习资料分享
原答案已经总结到下面的回答中了:
搞 Java 的年薪 40W 是什么水平?关注Java全栈学习专栏,获取更多Java知识:
Java全栈学习资源库Java构架师技术栈随着时代发展的要求,技术的不断更新,现在的项目呈现三高和三V的特征:
海量Velume
多样Variety
实时Velocity
高并发
高可用
高性能
过去学到框架就可以去找工作了,实现高薪就业,但是现在从JavaSE基础道SSM框架只是Java的基础,掌握构架师技术已经势在必行。
学习主线:
Java基础 JavaSE高级+Web前端E部分 >JavaWeb 框架 Java构架师
1、Java基础知识
了解Java发展历史
掌握Java基本语法
掌握Java常用IDE的使用
Java语言特色
面向对象思维
能够独立编写简单的Java程序
配套视频教程:
Java轻松入门经典教程[柠檬学院]-学习视频教程-培训课程-腾讯课堂学习内容:
2、JavaSe高级部分+Web前端部分
深入理解面向对象编程思维
掌握常用的类库,如List、IO、Date、System、Runtime、Math、Calendar等。
掌握Java异常处理,学会使用异常来处理一些无法掌握又必须的部分。
掌握Java网络编程,熟悉Socket实现原理。
掌握Html+css+js盒子模型,掌握响应式布局框架。
学习内容:
3、JavaWeb技术
掌握Servlet、JDBC、JSP核心技术。
掌握关系型数据库Mysql。
理解MVC三层构架。
能够独立制作JavaWeb系统。
4、框架
Spring5,做应用必不可少的最新框架
SpringMvc,经典MVC框架
MyBatis,玩数据库必不可少的组件
项目工程化与工具(Maven、Jenkins、Sonar、Git)
学习内容:Spring、SpringMVC,持久层API、项目构建工具Maven、安全框架Shino、面向服务编程WebService、企业级搜索应用服务器Lucene+Solr、工作流引擎Activiti。
柠檬学院李伟:什么是SSM框架5、Java高级构架师
配套视频:
Java构架师技术栈/微服务/源码分析/分布式/高并发/性能优化学习内容:
我觉得Java大致学习路径是:基础——>底层——>进阶——>高级——>架构——>拓展
每一个专题都有很多丰富的知识点。总结脑图如下(文字目录及分章介绍:https://github.com/hollischuang/toBeTopJavaer):
想要获得整套高清思维导图,可以关注我的公众号:Hollis,在后台回复:成神导图
基础
底层
进阶
http://weixin.qq.com/r/mDiWjo-EGdJmrcvt922K123 (二维码自动识别)
高级
架构
http://weixin.qq.com/r/mDiWjo-EGdJmrcvt922K123 (二维码自动识别)
拓展
http://weixin.qq.com/r/mDiWjo-EGdJmrcvt922K123 (二维码自动识别)
已拿BAT中和一些创业公司的年薪近35W的java的offer,来回答一发。我把所有需要的知识点罗列了出来,大部分有答案,少部分没有答案,可以说把下面这些内容搞懂,你就可以自诩精通Java后端了。
作者 Redfisky 链接:3万字英国留学生Java后台面经,中offer率5/7_留学生_牛客网
全文分为:基础知识和进阶知识
下文java必会知识附答案!并为大家整理了一个pdf,所有的知识点和答案都在pdf里面。
必会知识点及其答案!!!
Java基础知识(*)
- https://blog.csdn.net/qq_16633405/article/details/79211002
Spring Boot 启动 流程(*)
- https://juejin.im/post/5b679fbc5188251aad213110#heading-0
Spring 一些面试题(*)
- https://www.ctolib.com/topics-35589.html
匿名内部类编译class(*)
- https://blog.csdn.net/lazyer_dog/article/details/50669473
为什么集合类没有实现Cloneable和Serializable接口?
- https://www.nowcoder.com/questionTerminal/2a4902f67d5b49b6b4c05f9d7e422caf
自动装箱原理
- https://www.jianshu.com/p/0ce2279c5691
final关键字
- http://www.importnew.com/7553.html
基于Redis的分布式锁
- https://segmentfault.com/a/1190000012919740
数据库分布式锁
- http://www.hollischuang.com/archives/1716
防备DDOS攻击(*)
- https://www.zhihu.com/question/19581905
什么时候Mysql调用行锁?(*)
- https://blog.csdn.net/songwei128/article/details/43418343
CMS,G1(*)
- https://crowhawk.github.io/2017/08/15/jvm_3/
内部类,外部类互访(*)
- https://blog.csdn.net/jueblog/article/details/13434551
- https://blog.csdn.net/Van_L_/article/details/54667365
设计模式(*) 熟背单例模式和工厂模式,会写适配器和建造者也行
- https://www.jianshu.com/p/8a293e4a888e
- https://segmentfault.com/a/1190000004255439
深拷贝,浅拷贝(*)
- https://segmentfault.com/a/1190000010648514
泛型擦除
- https://blog.csdn.net/briblue/article/details/76736356
Java 8 Stream, 函数编程
- https://www.jianshu.com/p/0c07597d8311
- https://www.jianshu.com/p/9bd647bcf1e3
中断线程
- https://www.jianshu.com/p/264d4e1b76af
Lock,tryLock,lockInterruptibly区别
- https://blog.csdn.net/u013851082/article/details/70140223
JUC
- http://www.cnblogs.com/chenpi/p/5358579.html#_label2
- http://www.cnblogs.com/chenpi/p/5614290.html
NIO
- https://blog.csdn.net/u013063153/article/details/76473578
- https://www.jianshu.com/p/052035037297
- https://segmentfault.com/a/1190000006824196
Start和run区别(*)
- https://blog.csdn.net/qq_36544760/article/details/79380963
jvm内存屏障
- https://www.jianshu.com/p/2ab5e3d7e510
Java构造器能被重载,但是不能被重写(*)
- https://blog.csdn.net/weixin_36513603/article/details/54968094
HttpSession
- https://blog.csdn.net/zy2317878/article/details/80275463
Thread类的方法
- https://blog.csdn.net/gxx_csdn/article/details/79210192
String是值类型,还是引用类型(*)
- https://blog.csdn.net/a220315410/article/details/27743607
Redis 实现消息队列
- 消息/订阅+List
- https://segmentfault.com/a/1190000012244418
minor gc full gc 区别(*)
- https://blog.csdn.net/u010796790/article/details/52213708
Java如何查看死锁
- https://blog.csdn.net/u014039577/article/details/52351626
- https://juejin.im/post/5aaf6ee76fb9a028d3753534
c3p0,dbcp与druid
- https://blog.csdn.net/qq_34359363/article/details/72763491
Spring Bean 生命周期(*)
- https://www.jianshu.com/p/3944792a5fff
Spring的BeanFactory和ApplicationContext的区别?
- ApplicationContext是实现类,继承ListableBeanFactory(继承BeanFactory),功能更多
- ApplicationContext默认立即加载,BeanFactory懒加载
- https://my.oschina.net/yao00jun/blog/215642
- https://blog.csdn.net/qq_36748278/article/details/78264764
Java 如何有效地避免OOM:善于利用软引用和弱引用
- https://www.cnblogs.com/dolphin0520/p/3784171.html
分布式数据库主键生成策略(*)
- https://www.jianshu.com/p/a0a3aa888a49
- https://tech.meituan.com/MT_Leaf.html
String底层(*)
- https://blog.csdn.net/yadicoco49/article/details/77627302
count(1)、count(*)与count(列名)的执行区别
- https://blog.csdn.net/iFuMI/article/details/77920767
主键,唯一索引区别
- 1)主键一定会创建一个唯一索引,但是有唯一索引的列不一定是主键;
- 2)主键不允许为空值,唯一索引列允许空值;
- 3)一个表只能有一个主键,但是可以有多个唯一索引;
- 4)主键可以被其他表引用为外键,唯一索引列不可以;
- 5)主键是一种约束,而唯一索引是一种索引,是表的冗余数据结构,两者有本质的差别
死锁 产生死锁的四个必要条件:
- 互斥条件:一个资源每次只能被一个进程使用。
- 占有且等待:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不可强行占有:进程已获得的资源,在末使用完之前,不能强行剥夺。
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
避免死锁: https://segmentfault.com/a/1190000000378725
- 确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生.
- 另外一个可以避免死锁的方法是在尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程中若超过了这个时限该线程则放弃对该锁请求。若一个线程没有在给定的时限内成功获得所有需要的锁,则会进行回退并释放所有已经获得的锁,然后等待一段随机的时间再重试。
- 死锁检测是一个更好的死锁预防机制,它主要是针对那些不可能实现按序加锁并且锁超时也不可行的场景。
乐观锁,悲观锁(*)
- https://blog.csdn.net/lovejj1994/article/details/79116272
公平锁、非公平锁
- 公平锁(Fair):加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得 非公平锁(Nonfair):加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待 非公平锁性能比公平锁高5~10倍,因为公平锁需要在多核的情况下维护一个队列 Java中的ReentrantLock 默认的lock()方法采用的是非公平锁。
OOM分析
- https://blog.csdn.net/zheng12tian/article/details/40617369
JVM调优参数 知道-Xms,-Xmx,-XX:NewRatio=n,会算就行,笔试题考过
- https://www.jianshu.com/p/a2a6a0995fee
堆设置
- -Xms:初始堆大小 -Xmx:最大堆大小 -XX:NewSize=n:设置年轻代大小 -XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4 -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5 -XX:MaxPermSize=n:设置持久代大小
收集器设置
- -XX:+UseSerialGC:设置串行收集器 -XX:+UseParallelGC:设置并行收集器 -XX:+UseParalledlOldGC:设置并行年老代收集器 -XX:+UseConcMarkSweepGC:设置并发收集器
垃圾回收统计信息
- -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:filename
并行收集器设置
- -XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。 -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间 -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
并发收集器设置
- -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。 -XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
调优总结 年轻代大小选择
- 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
年老代大小选择
- 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得: 并发垃圾收集信息 持久代并发收集次数 传统GC信息 花在年轻代和年老代回收上的时间比例 减少年轻代和年老代花费的时间,一般会提高应用的效率 吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
较小堆引起的碎片问题
- 因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置: -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。 -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩
synchronized实现原理(*)
- https://blog.csdn.net/javazejian/article/details/72828483
- 内存对象头, Mark Word保存锁信息
- JVM层:Monitor对象,字节码中的monitorenter 和 monitorexit 指令
- 无锁,偏向锁,轻量级锁(自选),重量级锁
- 可重入
- notify/notifyAll和wait方法,在使用这3个方法时,必须处于synchronized代码块或者synchronized方法中,否则就会抛出IllegalMonitorStateException异常,这是因为调用这几个方法前必须拿到当前对象的监视器monitor对象,也就是说notify/notifyAll和wait方法依赖于monitor对象,在前面的分析中,我们知道monitor 存在于对象头的Mark Word 中(存储monitor引用指针),而synchronized关键字可以获取 monitor ,这也就是为什么notify/notifyAll和wait方法必须在synchronized代码块或者synchronized方法调用的原因.
synchronized, lock区别(*)
- https://blog.csdn.net/u012403290/article/details/64910926
Spring容器中Bean的作用域(*) 当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域:
- singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
- prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
- request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效
- session:对于每次HTTP Session,使用session定义的Bean产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效
- globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效 其中比较常用的是singleton和prototype两种作用域。对于singleton作用域的Bean,每次请求该Bean都将获得相同的实例。容器负责跟踪Bean实例的状态,负责维护Bean实例的生命周期行为;如果一个Bean被设置成prototype作用域,程序每次请求该id的Bean,Spring都会新建一个Bean实例,然后返回给程序。在这种情况下,Spring容器仅仅使用new 关键字创建Bean实例,一旦创建成功,容器不在跟踪实例,也不会维护Bean实例的状态。 如果不指定Bean的作用域,Spring默认使用singleton作用域。Java在创建Java实例时,需要进行内存申请;销毁实例时,需要完成垃圾回收,这些工作都会导致系统开销的增加。因此,prototype作用域Bean的创建、销毁代价比较大。而singleton作用域的Bean实例一旦创建成功,可以重复使用。因此,除非必要,否则尽量避免将Bean被设置成prototype作用域。
Spring IOC实现原理, 相关知识(*)
Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配好Bean之间的依赖关系,为上层应用提供准备就绪的运行环境。
Bean缓存池:HashMap实现
Spring 通过一个配置文件描述 Bean 及 Bean 之间的依赖关系,利用 Java 语言的反射功能实例化 Bean 并建立 Bean 之间的依赖关系。 Spring 的 IoC 容器在完成这些底层工作的基础上,还提供了 Bean 实例缓存、生命周期管理、 Bean 实例代理、事件发布、资源装载等高级服务。
BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;
ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合我们都直接使用 ApplicationContext 而非底层的 BeanFactory。
BeanDefinitionRegistry: Spring 配置文件中每一个节点元素在 Spring 容器里都通过一个 BeanDefinition 对象表示,它描述了 Bean 的配置信息。而 BeanDefinitionRegistry 接口提供了向容器手工注册 BeanDefinition 对象的方法。
BeanFactory 接口位于类结构树的顶端 ,它最主要的方法就是 getBean(String beanName),该方法从容器中返回特定名称的 Bean,BeanFactory 的功能通过其他的接口得到不断扩展:
ListableBeanFactory:该接口定义了访问容器中 Bean 基本信息的若干方法,如查看Bean 的个数、获取某一类型 Bean 的配置名、查看容器中是否包括某一 Bean 等方法;
HierarchicalBeanFactory:父子级联 IoC 容器的接口,子容器可以通过接口方法访问父容器; 通过 HierarchicalBeanFactory 接口, Spring 的 IoC 容器可以建立父子层级关联的容器体系,子容器可以访问父容器中的 Bean,但父容器不能访问子容器的 Bean。Spring 使用父子容器实现了很多功能,比如在 Spring MVC 中,展现层 Bean 位于一个子容器中,而业务层和持久层的 Bean 位于父容器中。这样,展现层 Bean 就可以引用业务层和持久层的 Bean,而业务层和持久层的 Bean 则看不到展现层的 Bean。
ConfigurableBeanFactory:是一个重要的接口,增强了 IoC 容器的可定制性,它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法;
AutowireCapableBeanFactory:定义了将容器中的 Bean 按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法;
SingletonBeanRegistry:定义了允许在运行期间向容器注册单实例 Bean 的方法;
@Bean, @Component 区别
- Componet 一般放在类上面,Bean放在方法上面,自己可控制是否生成bean. bean 一般会放在classpath scanning路径下面,会自动生成bean. 有Componet /bean生成的bean都提供给autowire使用.
- 在@Component中(@Component标注的类,包括@Service,@Repository, @Controller)使用@Bean注解和在@Configuration中使用是不同的。在@Component类中使用方法或字段时不会使用CGLIB增强(及不使用代理类:调用任何方法,使用任何变量,拿到的是原始对象,后面会有例子解释)。而在@Configuration类中使用方法或字段时则使用CGLIB创造协作对象(及使用代理:拿到的是代理对象);当调用@Bean注解的方法时它不是普通的Java语义,而是从容器中拿到的由Spring生命周期管理、被Spring代理甚至依赖于其他Bean的对象引用。在@Component中调用@Bean注解的方法和字段则是普通的Java语义,不经过CGLIB处理。
如何停止线程?
- 主线程提供volatile boolean flag, 线程内while判断flag
- 线程内while(!this.isInterrupted), 主线程里调用interrupt
- if(this.isInterrupted) throw new InterruptedException() 或return,主线程里调用interrupt
- 将一个线程设置为守护线程后,当进程中没有非守护线程后,守护线程自动结束
多线程实现方式?(*)
- extends Thread
- implements Runnable
- implements Callable, 重写call, 返回future (主线程可以用线程池submit)
线程池(*) 线程池处理过程:
- 如果当前运行的线程少于corePoolSize,则创建新线程来执行任务(注意,执行这一步骤需要获取全局锁)。
- 如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQueue。
- 如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务(注意,执行这一步骤需要获取全局锁)。
- 如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,并调用RejectedExecutionHandler.rejectedExecution()方法。
四种线程池:
- CachedThreadPool
- FixedThreadPool
- ScheduledThreadPool
- SingleThreadExecutor
创建线程池的参数:
- corePoolSize(线程池的基本大小):当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有基本线程。
- runnableTaskQueue(任务队列):用于保存等待执行的任务的阻塞队列。可以选择以下几个阻塞队列。 ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原则对元素进行排序。 LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。 SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于Linked-BlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。 PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
- maximumPoolSize(线程池最大数量):线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是,如果使用了无界的任务队列这个参数就没什么效果。
- ThreadFactory:用于设置创建线程的工厂
- RejectedExecutionHandler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。在JDK 1.5中Java线程池框架提供了以下4种策略。 AbortPolicy:直接抛出异常。 CallerRunsPolicy:只用调用者所在线程来运行任务。 DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。 DiscardPolicy:不处理,丢弃掉。
**ArrayList,LinkedList **
- ArrayList初始化可以指定大小,知道大小的建议指定 arraylist添加元素的时候,需要判断存放元素的数组是否需要扩容(扩容大小是原来大小的1/2+1)
- LinkedList添加、删除元素通过移动指针 LinkedList遍历比arraylist慢,建议用迭代器
- ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 对于随机访问get和set,ArrayList优于LinkedList,因为ArrayList可以随机定位,而LinkedList要移动指针一步一步的移动到节点处。(参考数组与链表来思考)
- 对于新增和删除操作add和remove,LinedList比较占优势,只需要对指针进行修改即可,而ArrayList要移动数据来填补被删除的对象的空间。
HashMap原理(*)
- HashMap最多只允许一条Entry的键为Null(多条会覆盖),但允许多条Entry的值为Null
- HashSet 本身就是在 HashMap 的基础上实现的.
- 若负载因子越大,那么对空间的利用更充分,但查找效率的也就越低;若负载因子越小,那么哈希表的数据将越稀疏,对空间造成的浪费也就越严重。系统默认负载因子0.75
- 调用put方法存值时,HashMap首先会调用Key的hashCode方法,然后基于此获取Key哈希码,通过哈希码快速找到某个桶,这个位置可以被称之为bucketIndex.如果两个对象的hashCode不同,那么equals一定为false;否则,如果其hashCode相同,equals也不一定为 true。所以,理论上,hashCode可能存在碰撞的情况,当碰撞发生时,这时会取出bucketIndex桶内已存储的元素,并通过hashCode() 和 equals()来逐个比较以判断Key是否已存在。如果已存在,则使用新Value值替换旧Value值,并返回旧Value值;如果不存在,则存放新的键值对到桶中。因此,在 HashMap中,equals() 方法只有在哈希码碰撞时才会被用到。
- 首先,判断key是否为null,若为null,则直接调用putForNullKey方法;若不为空,则先计算key的hash值,然后根据hash值搜索在table数组中的索引位置,如果table数组在该位置处有元素,则查找是否存在相同的key,若存在则覆盖原来key的value,否则将该元素保存在链头(最先保存的元素放在链尾)。此外,若table在该处没有元素,则直接保存。
- HashMap 永远都是在链表的表头添加新元素。
hash()和indexFor()
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
static int indexFor(int h, int length) {
return h & (length-1); // 作用等价于取模运算,但这种方式效率更高
}
- hash() 方法用于对Key的hashCode进行重新计算,而 indexFor()方法用于生成这个Entry对象的插入位置。当计算出来的hash值与hashMap的(length-1)做了&运算后,会得到位于区间[0,length-1]的一个值。特别地,这个值分布的越均匀,HashMap 的空间利用率也就越高,存取效率也就越好,保证元素均匀分布到table的每个桶中以便充分利用空间。
- hash():使用hash()方法对一个对象的hashCode进行重新计算是为了防止质量低下的hashCode()函数实现。由于hashMap的支撑数组长度总是2 的幂次,通过右移可以使低位的数据尽量的不同,从而使hash值的分布尽量均匀。
- indexFor():保证元素均匀分布到table的每个桶中; 当length为2的n次方时,h&(length -1)就相当于对length取模,而且速度比直接取模要快得多,这是HashMap在速度上的一个优化.
扩容resize()和重哈希transfer()
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
// 若 oldCapacity 已达到最大值,直接将 threshold 设为 Integer.MAX_VALUE
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return; // 直接返回
}
// 否则,创建一个更大的数组
Entry[] newTable = new Entry[newCapacity];
//将每条Entry重新哈希到新的数组中
transfer(newTable);
table = newTable;
threshold = (int) (newCapacity * loadFactor); // 重新设定 threshold
}
void transfer(Entry[] newTable) {
// 将原数组 table 赋给数组 src
Entry[] src = table;
int newCapacity = newTable.length;
// 将数组 src 中的每条链重新添加到 newTable 中
for (int j = 0; j < src.length; j++) {
Entry e = src[j];
if (e != null) {
src[j] = null; // src 回收
// 将每条链的每个元素依次添加到 newTable 中相应的桶中
do {
Entry next = e.next;
// e.hash指的是 hash(key.hashCode())的返回值;
// 计算在newTable中的位置,注意原来在同一条子链上的元素可能被分配到不同的子链
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);
}
}
}
- 为了保证HashMap的效率,系统必须要在某个临界点进行扩容处理,该临界点就是HashMap中元素的数量在数值上等于threshold(table数组长度*加载因子)
- 重哈希的主要是一个重新计算原HashMap中的元素在新table数组中的位置并进行复制处理的过程
HashMap 的底层数组长度为何总是2的n次方
- 当底层数组的length为2的n次方时, h&(length - 1) 就相当于对length取模,而且速度比直接取模快得多,这是HashMap在速度上的一个优化
- 不同的hash值发生碰撞的概率比较小,这样就会使得数据在table数组中分布较均匀,空间利用率较高,查询速度也较快
ConcurrenytHashMap原理(*)
- https://blog.csdn.net/justloveyou_/article/details/72783008
- 通过锁分段技术保证并发环境下的写操作; 通过 HashEntry的不变性、Volatile变量的内存可见性和加锁重读机制保证高效、安全的读操作; 通过不加锁和加锁两种方案控制跨段操作的的安全性。
HashMap线程不安全
- https://blog.csdn.net/justloveyou_/article/details/72783008
- 在HashMap进行扩容重哈希时导致Entry链形成环。一旦Entry链中有环,势必会导致在同一个桶中进行插入、查询、删除等操作时陷入死循环。
Segment数组
static final class Segment extends ReentrantLock
implements Serializable {
transient volatile int count; // Segment中元素的数量,可见的
transient int modCount; //对count的大小造成影响的操作的次数(比如put或者remove操作)
transient int threshold; // 阈值,段中元素的数量超过这个值就会对Segment进行扩容
transient volatile HashEntry[] table; // 链表数组
final float loadFactor; // 段的负载因子,其值等同于ConcurrentHashMap的负载因子
...
}
- Segment 类继承于 ReentrantLock 类,从而使得 Segment 对象能充当锁的角色
- 在Segment类中,count 变量是一个计数器,它表示每个 Segment 对象管理的 table 数组包含的 HashEntry 对象的个数,也就是 Segment 中包含的 HashEntry 对象的总数。特别需要注意的是,之所以在每个 Segment 对象中包含一个计数器,而不是在 ConcurrentHashMap 中使用全局的计数器,是对 ConcurrentHashMap 并发性的考虑:因为这样当需要更新计数器时,不用锁定整个ConcurrentHashMap。事实上,每次对段进行结构上的改变,如在段中进行增加/删除节点(修改节点的值不算结构上的改变),都要更新count的值,此外,在JDK的实现中每次读取操作开始都要先读取count的值。特别需要注意的是,count是volatile的,这使得对count的任何更新对其它线程都是立即可见的。modCount用于统计段结构改变的次数,主要是为了检测对多个段进行遍历过程中某个段是否发生改变.table是一个典型的链表数组,而且也是volatile的,这使得对table的任何更新对其它线程也都是立即可见的。
HashEntry
static final class HashEntry {
final K key; // 声明 key 为 final 的
final int hash; // 声明 hash 值为 final 的
volatile V value; // 声明 value 被volatile所修饰
final HashEntry next; // 声明 next 为 final 的
HashEntry(K key, int hash, HashEntry next, V value) {
this.key = key;
this.hash = hash;
this.next = next;
this.value = value;
}
@SuppressWarnings("unchecked")
static final HashEntry[] newArray(int i) {
return new HashEntry[i];
}
}
- 在HashEntry类中,key,hash和next域都被声明为final的,value域被volatile所修饰,因此HashEntry对象几乎是不可变的,这是ConcurrentHashmap读操作并不需要加锁的一个重要原因
- 由于value域被volatile修饰,所以其可以确保被读线程读到最新的值,这是ConcurrentHashmap读操作并不需要加锁的另一个重要原因
put(), get()
- 不允许key值为null,也不允许value值为null
- HashTable 和由同步包装器包装的HashMap每次只能有一个线程执行读或写操作,ConcurrentHashMap 在并发访问性能上有了质的提高。在理想状态下,ConcurrentHashMap 可以支持 16 个线程执行并发写操作(如果并发级别设置为 16),及任意数量线程的读操作。 重哈希rehash()
- ConcurrentHashMap的重哈希实际上是对ConcurrentHashMap的某个段的重哈希,因此ConcurrentHashMap的每个段所包含的桶位自然也就不尽相同
存在key-value为null的特殊情况
V get(Object key, int hash) {
if (count != 0) { // read-volatile,首先读 count 变量
HashEntry e = getFirst(hash); // 获取桶中链表头结点
while (e != null) {
if (e.hash == hash && key.equals(e.key)) { // 查找链中是否存在指定Key的键值对
V v = e.value;
if (v != null) // 如果读到value域不为 null,直接返回
return v;
// 如果读到value域为null,说明发生了重排序,加锁后重新读取
return readValueUnderLock(e); // recheck
}
e = e.next;
}
}
return null; // 如果不存在,直接返回null
}
- 初始化HashEntry时发生的指令重排序导致的,也就是在HashEntry初始化完成之前便返回了它的引用
- 加锁重读
读操作不需要加锁
- 用HashEntery对象的不变性来降低读操作对加锁的需求;
- 用Volatile变量协调读写线程间的内存可见性;
- 若读时发生指令重排序现象,则加锁重读;
结构性操作的并发安全
remove(Object key, int hash, Object value) {
lock(); // 加锁
try {
int c = count - 1;
HashEntry[] tab = table;
int index = hash & (tab.length - 1); // 定位桶
HashEntry first = tab[index];
HashEntry e = first;
while (e != null && (e.hash != hash || !key.equals(e.key))) // 查找待删除的键值对
e = e.next;
V oldValue = null;
if (e != null) { // 找到
V v = e.value;
if (value == null || value.equals(v)) {
oldValue = v;
// All entries following removed node can stay
// in list, but all preceding ones need to be
// cloned.
++modCount;
// 所有处于待删除节点之后的节点原样保留在链表中
HashEntry newFirst = e.next;
// 所有处于待删除节点之前的节点被克隆到新链表中
for (HashEntry p = first; p != e; p = p.next)
newFirst = new HashEntry(p.key, p.hash,newFirst, p.value);
tab[index] = newFirst; // 将删除指定节点并重组后的链重新放到桶中
count = c; // write-volatile,更新Volatile变量count
}
}
return oldValue;
} finally {
unlock(); // finally子句解锁
}
}
- clear操作只是把ConcurrentHashMap中所有的桶置空,每个桶之前引用的链表依然存在,只是桶不再引用这些链表而已,而链表本身的结构并没有发生任何修改。
- put操作如果需要插入一个新节点到链表中时会在链表头部插入这个新节点,此时链表中的原有节点的链接并没有被修改
- 在执行remove操作时,原始链表并没有被修改
- 只要之前对链表做结构性修改操作的写线程M在退出写方法前写volatile变量count(segment中的,segment中元素的个数),读线程N就能读取到这个volatile变量count的最新值
跨segment操作
- size(): JDK只需要在统计size前后比较modCount(Segment中的)是否发生变化就可以得知容器的大小是否发生变化
- size方法主要思路是先在没有锁的情况下对所有段大小求和,这种求和策略最多执行RETRIES_BEFORE_LOCK次(默认是两次):在没有达到RETRIES_BEFORE_LOCK之前,求和操作会不断尝试执行(这是因为遍历过程中可能有其它线程正在对已经遍历过的段进行结构性更新);在超过RETRIES_BEFORE_LOCK之后,如果还不成功就在持有所有段锁的情况下再对所有段大小求和。
JVM内存模型(*) 必考,熟背
- 线程私有的数据区 包括 程序计数器、 虚拟机栈 和 本地方法栈
- 线程共享的数据区 具体包括 Java堆 和 方法区
线程计数器
- 在多线程情况下,当线程数超过CPU数量或CPU内核数量时,线程之间就要根据 时间片轮询抢夺CPU时间资源。也就是说,在任何一个确定的时刻,一个处理器都只会执行一条线程中的指令。因此,为了线程切换后能够恢复到正确的执行位置,每条线程都需要一个独立的程序计数器去记录其正在执行的字节码指令地址。
虚拟机栈
- 每个方法从调用直至完成的过程,对应一个栈帧在虚拟机栈中入栈到出栈的过程
本地方法栈
- 本地方法栈与Java虚拟机栈非常相似,也是线程私有的,区别是虚拟机栈为虚拟机执行 Java 方法服务,而本地方法栈为虚拟机执行 Native 方法服务。与虚拟机栈一样,本地方法栈区域也会抛出 StackOverflowError 和 OutOfMemoryError 异常
Java堆
- Java 堆的唯一目的就是存放对象实例,几乎所有的对象实例(和数组)都在这里分配内存
- Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。而且,Java堆在实现时,既可以是固定大小的,也可以是可拓展的,并且主流虚拟机都是按可扩展来实现的(通过-Xmx(最大堆容量) 和 -Xms(最小堆容量)控制)。如果在堆中没有内存完成实例分配,并且堆也无法再拓展时,将会抛出 OutOfMemoryError 异常。
- TLAB (线程私有分配缓冲区) : 虚拟机为新生对象分配内存时,需要考虑修改指针 (该指针用于划分内存使用空间和空闲空间) 时的线程安全问题,因为存在可能出现正在给对象A分配内存,指针还未修改,对象B又同时使用原来的指针分配内存的情况。TLAB 的存在就是为了解决这个问题:每个线程在Java堆中预先分配一小块内存 TLAB,哪个线程需要分配内存就在自己的TLAB上进行分配,若TLAB用完并分配新的TLAB时,再加同步锁定,这样就大大提升了对象内存分配的效率。
方法区
- 方法区与Java堆一样,也是线程共享的并且不需要连续的内存,其用于存储已被虚拟机加载的 类信息、常量、静态变量、即时编译器编译后的代码等数据
- 运行时常量池:是方法区的一部分,用于存放编译期生成的各种 字面量 和 符号引用. 字面量比较接近Java语言层次的常量概念,如文本字符串、被声明为final的常量值. 符号引用:包括以下三类常量:类和接口的全限定名、字段的名称和描述符 和 方法的名称和描述符.
方法区的回收
- 主要是针对 常量池的回收 (判断引用) 和 对类型的卸载
- 回收类: 1) 该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例加载 2) 该类的ClassLoader已经被回收 3) 该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
垃圾回收机制(*) 必考,熟背
引用计数法
- 循环引用
可达性分析算法
- 通过一系列的名为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain)。当一个对象到 GC Roots 没有任何引用链相连(用图论的话来说就是从 GC Roots 到这个对象不可达)时,则证明此对象是不可用的
- 虚拟机栈(栈帧中的局部变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中Native方法引用的对象
标记清除算法
- 标记-清除算法分为标记和清除两个阶段。该算法首先从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象并进行回收
- 效率问题:标记和清除两个过程的效率都不高;
- 空间问题:标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,因此标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作
复制算法
- 复制算法将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这种算法适用于对象存活率低的场景,比如新生代。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。
- 实践中会将新生代内存分为一块较大的Eden空间和两块较小的Survivor空间 (如下图所示),每次使用Eden和其中一块Survivor。当回收时,将Eden和Survivor中还存活着的对象一次地复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是 8:1,也就是每次新生代中可用内存空间为整个新生代容量的90% ( 80%+10% ),只有10% 的内存会被“浪费”。
- 现在商用的虚拟机都采用这种算法来回收新生代
为什么分代收集
- 不同的对象的生命周期(存活情况)是不一样的,而不同生命周期的对象位于堆中不同的区域,因此对堆内存不同区域采用不同的策略进行回收可以提高 JVM 的执行效率.
新生代进入老生代的情况
- 对象优先在Eden分配,当Eden区没有足够空间进行分配时,虚拟机将发起一次MinorGC。现在的商业虚拟机一般都采用复制算法来回收新生代,将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。 当进行垃圾回收时,将Eden和Survivor中还存活的对象一次性地复制到另外一块Survivor空间上,最后处理掉Eden和刚才的Survivor空间。(HotSpot虚拟机默认Eden和Survivor的大小比例是8:1)当Survivor空间不够用时,需要依赖老年代进行分配担保。
- 大对象直接进入老年代。所谓的大对象是指,需要大量连续内存空间的Java对象,最典型的大对象就是那种很长的字符串以及数组。
- 长期存活的对象(-XX:MaxTenuringThreshold)将进入老年代。当对象在新生代中经历过一定次数(默认为15)的Minor GC后,就会被晋升到老年代中。
- 动态对象年龄判定。为了更好地适应不同程序的内存状况,虚拟机并不是永远地要求对象年龄必须达到了MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。
内存分配担保机制
- 我们知道如果对象在复制到Survivor区时若Survivor空间不足,则会出发担保机制,将对象转入老年代;但老年代的能力也不是无限的,因此需要在minor GC时做一个是否需要Major GC 的判断:
- 如果老年代的剩余空间 < 之前转入老年代的对象的平均大小,则触发Major GC
- 如果老年代的剩余空间 > 之前转入老年代的对象的平均大小,并且允许担保失败,则直接Minor GC,不需要做Full GC
- 如果老年代的剩余空间 > 之前转入老年代的对象的平均大小,并且不允许担保失败,则触发Major GC 出发点还是尽量为对象分配内存。但是一般会配置允许担保失败,避免频繁的去做Full GC。
标记整理算法
- 标记整理算法的标记过程类似标记清除算法,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存,类似于磁盘整理的过程,该垃圾回收算法适用于对象存活率高的场景(老年代)
- 无内存碎片
新生代、老年代、永久代
- 新生代的目标就是尽可能快速的收集掉那些生命周期短的对象,一般情况下,所有新生成的对象首先都是放在新生代的. 如果老年代也满了,就会触发一次FullGC,也就是新生代、老年代都进行回收。注意,新生代发生的GC也叫做MinorGC,MinorGC发生频率比较高,不一定等 Eden区满了才触发。
- 老年代存放的都是一些生命周期较长的对象,就像上面所叙述的那样,在新生代中经历了N次垃圾回收后仍然存活的对象就会被放到老年代中
- 永久代主要用于存放静态文件,如Java类、方法等
垃圾收集器
- Serial收集器(复制算法): 新生代单线程收集器,标记和清理都是单线程,优点是简单高效;
- Serial Old收集器 (标记-整理算法): 老年代单线程收集器,Serial收集器的老年代版本;
- ParNew收集器 (复制算法):新生代收并行集器,实际上是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现;
- Parallel Scavenge收集器 (复制算法): 新生代并行收集器,追求高吞吐量,高效利用 CPU。吞吐量 =用户线程时间/(用户线程时间+GC线程时间),高吞吐量可以高效率的利用CPU时间,尽快完成程序的运算任务,适合后台应用等对交互相应要求不高的场景;
- Parallel Old收集器 (标记-整理算法): 老年代并行收集器,吞吐量优先,Parallel Scavenge收集器的老年代版本;
- CMS(Concurrent Mark Sweep)收集器(标记-清除算法):老年代并行收集器,以获取最短回收停顿时间为目标的收集器,具有高并发、低停顿的特点,追求最短GC回收停顿时间。
- G1(Garbage First)收集器 (标记-整理算法):Java堆并行收集器,G1收集器是JDK1.7提供的一个新收集器,G1收集器基于“标记-整理”算法实现,也就是说不会产生内存碎片。此外,G1收集器不同于之前的收集器的一个重要特点是:G1回收的范围是整个Java堆(包括新生代,老年代),而前六种收集器回收的范围仅限于新生代或老年代。
CMS,G1
- https://blog.csdn.net/huanbia/article/details/75581423
内存泄露问题
- 静态集合类: 如 HashMap、Vector 等集合类的静态使用最容易出现内存泄露,因为这些静态变量的生命周期和应用程序一致,所有的对象Object也不能被释放
- 各种资源连接包括数据库连接、网络连接、IO连接等没有显式调用close关闭
- 监听器的使用,在释放对象的同时没有相应删除监听器的时候也可能导致内存泄露。
MYSQL索引(*)
建立索引
- 表的主键、外键必须有索引;
- 数据量超过300的表应该有索引;
- 经常与其他表进行连接的表,在连接字段上应该建立索引;
- 经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;
- 索引应该建在选择性高的字段上;
- 索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;
- 频繁进行数据操作的表,不要建立太多的索引;
索引失效
- 字符串不加单引号
- 将要使用的索引列不是复合索引列表中的第一部分,则不会使用索引
- 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null
- 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0
- 应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。
- 应尽量避免在 where 子句中使用 or 来连接条件 (用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到),否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num=10 or num=20
- 可以这样查询: select id from t where num=10 union all select id from t where num=20
- in 和 not in 也要慎用,因为IN会使系统无法使用索引,而只能直接搜索表中的数据。如: select id from t where num in(1,2,3)
- 对于连续的数值,能用 between 就不要用 in 了: select id from t where num between 1 and 3
- 尽量避免在索引过的字符数据中,使用非打头字母%搜索。这也使得引擎无法利用索引。 见如下例子: SELECT * FROM T1 WHERE NAME LIKE ‘%L%’ SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’ SELECT * FROM T1 WHERE NAME LIKE ‘L%’
- 即使NAME字段建有索引,前两个查询依然无法利用索引完成加快操作,引擎不得不对全表所有数据逐条操作来完成任务。而第三个查询能够使用索引来加快操作
- 应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描
- 应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描
- 不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引
共享锁,排他锁
- InnoDB普通 select 语句默认不加锁(快照读,MYISAM会加锁),而CUD操作默认加排他锁
- MySQL InnoDB存储引擎,实现的是基于多版本的并发控制协议——MVCC (Multi-Version Concurrency Control) (注:与MVCC相对的,是基于锁的并发控制,Lock-Based Concurrency Control)。MVCC最大的好处,相信也是耳熟能详:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能,这也是为什么现阶段,几乎所有的RDBMS,都支持了MVCC。
- 多版本并发控制(MVCC)是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。 这样在读操作不用阻塞写操作,写操作不用阻塞读操作的同时,避免了脏读和不可重复读.MVCC 在语境中倾向于 “对多行数据打快照造平行宇宙”,然而 CAS 一般只是保护单行数据而已
- 在MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)。快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。
- SELECT … LOCK IN SHARE MODE :共享锁(S锁, share locks)。其他事务可以读取数据,但不能对该数据进行修改,直到所有的共享锁被释放。
- SELECT … FOR UPDATE:排他锁(X锁, exclusive locks)。如果事务对数据加上排他锁之后,则其他事务不能对该数据加任何的锁。获取排他锁的事务既能读取数据,也能修改数据。
- InnoDB默认隔离级别 可重复读(Repeated Read)
- 查询字段未加索引(主键索引、普通索引等)时,使用表锁
- InnoDB行级锁基于索引实现
- 索引数据重复率太高会导致全表扫描:当表中索引字段数据重复率太高,则MySQL可能会忽略索引,进行全表扫描,此时使用表锁。可使用 force index 强制使用索引。
隔离级别
- Read Uncommitted(读取未提交内容): 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
- Read Committed(读取提交内容): 这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
- Repeatable Read(可重读): 这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
- Serializable(可串行化): 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争.
Spring IOC 怎么注入类,怎么实例化对象 实例化
- Spring IoC容器则需要根据Bean定义里的配置元数据使用反射机制来创建Bean
- 使用构造器实例化Bean 有参/无参;使用静态工厂实例化Bean;使用实例工厂实例化Bean.
- 使用@Autowire注解注入的时机则是容器刚启动的时候就开始注入;注入之前要先初始化bean;ApplicationContext 的初始化和BeanFactory 有一个重大的区别:BeanFactory在初始化容器时,并未实例化Bean,直到第一次访问某个Bean 时才实例目标Bean;而ApplicationContext 则在初始化应用上下文时就实例化所有单实例的Bean。
注入
- 接口、setter、构造器
AOP(*) 动态代理
@Aspect
public class Audience
{
@Before("execution(** concert.Performance.perform(..))") // 表演之前
public void silenceCellPhones()
{
System.out.println("Silencing cell phones");
}
@Before("execution(** concert.Performance.perform(..))") // 表演之前
public void takeSeats()
{
System.out.println("Taking seats");
}
@AfterReturning("execution(** concert.Performance.perform(..))") // 表演之后
public void applause()
{
System.out.println("CLAP CLAP CLAP!!!");
}
@AfterThrowing("execution(** concert.Performance.perform(..))") // 表演失败之后
public void demandRefound()
{
System.out.println("Demanding a refund");
}
}
- JDK动态代理,接口,用Proxy.newProxyInstance生成代理对象,InvocationHandler
- CGLIB,类,用enhancer生成代理对象,MethodInteceptor
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP ; 如果目标对象实现了接口,可以强制使用CGLIB实现AOP ; 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换;
- 切点+注解
- AspectJ是一个比较牛逼的AOP框架,他可以对类的成员变量,方法进行拦截。由于 AspectJ 是 Java 语言语法和语义的扩展,所以它提供了自己的一套处理方面的关键字。除了包含字段和方法之外,AspectJ 的方面声明还包含切入点和通知成员。 Spring AOP依赖的是 Spring 框架方便的、最小化的运行时配置,所以不需要独立的启动器。但是,使用这个技术,只能通知从 Spring 框架检索出的对象。Spring的AOP技术只能是对方法进行拦截。 在spring AOP中我们同样也可以使用类似AspectJ的注解来实现AOP功能,但是这里要注意一下,使AspectJ的注解时,AOP的实现方式还是Spring AOP。Spring缺省使用J2SE动态代理来作为AOP的代理,这样任何接口都可以被代理,Spring也可以使用CGLIB代理,对于需要代理类而不是代理接口的时候CGLIB是很有必要的。如果一个业务对象没有实现接口,默认就会使用CGLIB代理。 Spring AOP和AscpectJ之间的关系:Spring使用了和aspectj一样的注解,并使用Aspectj来做切入点解析和匹配。但是spring AOP运行时仍旧是纯的spring AOP,并不依赖于Aspectj的编译器或者织入器
volatile和内存模型(*)
happens-before
- 什么是happens-before 令A和B表示两组操作,如果A happens-before B,那么由A操作引起的内存变化,在B开始执行之前,都应该是可见的。 A happens-before B,不代表A在B之前执行.
- 如何确保happen-before 锁(互斥锁、读写锁等)、内存屏障
内存屏障
- 内存屏障是一个指令,这个指令可以保证屏障前后的指令遵守一定的顺序,并且保证一定的可见性
- 为了实现volatile的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。
Java内存模型
- 屏蔽各个硬件平台和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果
- Java内存模型 规定所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(类似于前面的高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作,并且每个线程不能访问其他线程的工作内存。
原子性
- 只有简单的读取、赋值(而且必须是将数字赋值给某个变量,变量之间的相互赋值不是原子操作)才是原子操作
- Java内存模型只保证了基本读取和赋值是原子性操作,如果要实现更大范围操作的原子性,可以通过 synchronized 和 Lock 来实现
可见性
- 当一个共享变量被 volatile 修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值. 通过 synchronized 和 Lock 也能够保证可见性,synchronized 和 Lock 能保证同一时刻只有一个线程获取锁然后执行同步代码,并且 在释放锁之前会将对变量的修改刷新到主存当中,因此可以保证可见性
有序性
- 指令重排序
- 不能由于 synchronized 和 Lock 可以让线程串行执行同步代码,就说它们可以保证指令不会发生重排序
volatile
- 保证了不同线程对共享变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值对其他线程来说是 立即可见
- 禁止进行指令重排序 (双重检查锁单例模式)
- synchronized 也可以保证可见性,因为每次运行synchronized块 或者 synchronized方法都会导致线程工作内存与主存的同步,使得其他线程可以取得共享变量的最新值。也就是说,synchronized 语义范围不但包括 volatile 具有的可见性,也包括原子性,但不能禁止指令重排序,这是二者一个功能上的差异
i被volatile修饰,如果多线程来运行i++,那么是否可以达到理想的效果?
- 不能,volatile不能保证操作的原子性
Sleep()和wait()的区别,使用wait()方法后,怎么唤醒线程(*)
笔试题经常考
- sleep方法只让出了CPU,而并不会释放同步资源锁
- wait()方法则是指当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行
- sleep()方法可以在任何地方使用;wait()方法则只能在同步方法或同步块中使用
- sleep()是线程线程类(Thread)的方法,调用会暂停此线程指定的时间,但监控依然保持,不会释放对象锁,到时间自动恢复;wait()是Object的方法,调用会放弃对象锁,进入等待队列,待调用notify()/notifyAll()唤醒指定的线程或者所有线程,才会进入锁池,不再次获得对象锁才会进入运行状态
- notify让之前调用wait的线程有权利重新参与线程的调度
Mybatis缓存(*)
- 一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。
- 二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存
- https://segmentfault.com/a/1190000013678579
Redis的数据结构(*)
- String, Hash, List, Set, ZSet
Hash底层结构
- redis的哈希对象的底层存储可以使用ziplist(压缩列表)和hashtable
Redis缓存怎么运行的?
- 使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库
- 主从复制
- 哨兵模式
持久化
- 快照文件
- AOF语句追加
过期策略
- https://blog.csdn.net/xiangnan129/article/details/54928672
反向代理是什么?
- 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。客户端只会得知反向代理的IP地址,而不知道在代理服务器后面的服务器簇的存在.
负载均衡是什么?
- 负载平衡(Load balancing)是一种计算机技术,用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。 使用带有负载平衡的多个服务器组件,取代单一的组件,可以通过冗余提高可靠性。负载平衡服务通常是由专用软件和硬件来完成。 主要作用是将大量作业合理地分摊到多个操作单元上进行执行,用于解决互联网架构中的高并发和高可用的问题。
单例模式(*)
必考,静态内部类,双重检查锁至少会写一个
- 私有的构造方法; 指向自己实例的私有静态引用; 以自己实例为返回值的静态的公有方法。
双重检查锁
public class Singleton2 {
private volatile static Singleton2 singleton2;
private Singleton2() {
}
public static Singleton2 getSingleton2() {
if (singleton2 == null) {
synchronized (Singleton2.class) {
if (singleton2 == null) {
singleton2 = new Singleton2();
}
}
}
return singleton2;
}
}
- 第一个if (instance == null),只有instance为null的时候,才进入synchronized. 第二个if (instance == null),是为了防止可能出现多个实例的情况。
- volatile: 主要在于singleton = new Singleton()这句,这并非是一个原子操作,事实上在 JVM 中这句话大概做了下面 3 件事情。 1. 给 singleton 分配内存 2. 调用 Singleton 的构造函数来初始化成员变量,形成实例 3. 将singleton对象指向分配的内存空间(执行完这步 singleton才是非 null 了)但是在 JVM 的即时编译器中存在指令重排序的优化。 也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2。如果是后者,则在 3 执行完毕、2 未执行之前,被线程二抢占了 ,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。
静态内部类
public class Singleton1 {
private Singleton1() {
}
public static final Singleton1 getSingleton1() {
return Singleton1Holder.singleton1;
}
private static class Singleton1Holder {
private static final Singleton1 singleton1 = new Singleton1();
}
}
ThreadLocal内存泄露?
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}
...
}
- ThreadLocalMap里面对Key的引用是弱引用。那么,就存在这样的情况:当释放掉对threadlocal对象的强引用后,map里面的value没有被回收,但却永远不会被访问到了,因此ThreadLocal存在着内存泄露问题
- Java为了最小化减少内存泄露的可能性和影响,在ThreadLocal进行get、set操作时会清除线程Map里所有key为null的value。所以最怕的情况就是,ThreadLocal对象设null了,开始发生“内存泄露”,然后使用线程池,线程结束后被放回线程池中而不销毁,那么如果这个线程一直不被使用或者分配使用了又不再调用get/set方法,那么这个期间就会发生真正的内存泄露。因此,最好的做法是:在不使用该ThreadLocal对象时,及时调用该对象的remove方法去移除ThreadLocal.ThreadLocalMap中的对应Entry.
线程死锁检测工具?
- Jconsole, Jstack, visualVM
线程池调优?
- 设置最大线程数,防止线程资源耗尽;
- 使用有界队列,从而增加系统的稳定性和预警能力(饱和策略);
- 根据任务的性质设置线程池大小:CPU密集型任务(CPU个数个线程),IO密集型任务(CPU个数两倍的线程),混合型任务(拆分)。
几种锁?
- 无锁状态,偏向锁状态,轻量级锁状态和重量级锁状态,它会随着竞争情况逐渐升级。锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。这种锁升级却不能降级的策略,目的是为了提高获得锁和释放锁的效率
偏向锁
- 偏向锁的目的是在某个线程获得锁之后,消除这个线程锁重入(CAS)的开销,看起来让这个线程得到了偏护
- 偏向锁使用了一种等到竞争出现才释放锁的机制,所以当其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁
自旋锁
- 线程的阻塞和唤醒需要CPU从用户态转为核心态,频繁的阻塞和唤醒对CPU来说是一件负担很重的工作. 所谓“自旋”,就是让线程去执行一个无意义的循环,循环结束后再去重新竞争锁,如果竞争不到继续循环,循环过程中线程会一直处于running状态,但是基于JVM的线程调度,会出让时间片,所以其他线程依旧有申请锁和释放锁的机会。
- 自旋锁省去了阻塞锁的时间空间(队列的维护等)开销,但是长时间自旋就变成了“忙式等待”,忙式等待显然还不如阻塞锁。所以自旋的次数一般控制在一个范围内,例如10,100等,在超出这个范围后,自旋锁会升级为阻塞锁。
轻量级锁
- 线程尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁,如果失败,则自旋获取锁,当自旋获取锁仍然失败时,表示存在其他线程竞争锁(两条或两条以上的线程竞争同一个锁),则轻量级锁会膨胀成重量级锁。
重量级锁
- 重量锁在JVM中又叫对象监视器(Monitor),它很像C中的Mutex,除了具备Mutex(0|1)互斥的功能,它还负责实现了Semaphore(信号量)的功能,也就是说它至少包含一个竞争锁的队列,和一个信号阻塞队列(wait队列),前者负责做互斥,后一个用于做线程同步。
innoDB和MyISAM的区别? (*)
- https://www.jianshu.com/p/a957b18ba40d
- InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;
- InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;
- InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
- InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
- Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;
索引失效 (*)
- https://blog.csdn.net/qq_32331073/article/details/79041232
MySQL 索引实现原理+几种索引 (*)
普通索引
- B+ree
- MyISAM的B+Tree的叶子节点上的data,并不是数据本身,而是数据存放的地址。主索引和辅助索引没啥区别,只是主索引中的key一定得是唯一的。这里的索引都是非聚簇索引.
InnoDB
- InnoDB 的数据文件本身就是索引文件,B+Tree的叶子节点上的data就是数据本身,key为主键,这是聚簇索引。
- 因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以 唯一 标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。
- 聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引(普通索引)搜索需要 检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录.
几种索引
- 主键索引;
- 唯一索引;
- 普通索引;
- 联合索引;
- 全文索引。
辅助索引
- https://www.cnblogs.com/xiangyangzhu/p/index.html
为什么用B+树
- https://blog.csdn.net/xlgen157387/article/details/79450295
- 在MySQL中的数据一般是放在磁盘中的,读取数据的时候肯定会有访问磁盘的操作,磁盘中有两个机械运动的部分,分别是盘片旋转和磁臂移动。盘片旋转就是我们市面上所提到的多少转每分钟,而磁盘移动则是在盘片旋转到指定位置以后,移动磁臂后开始进行数据的读写。那么这就存在一个定位到磁盘中的块的过程,而定位是磁盘的存取中花费时间比较大的一块,毕竟机械运动花费的时候要远远大于电子运动的时间。当大规模数据存储到磁盘中的时候,显然定位是一个非常花费时间的过程,但是我们可以通过B树进行优化,提高磁盘读取时定位的效率。
- 为什么B类树可以进行优化呢?我们可以根据B类树的特点,构造一个多阶的B类树,然后在尽量多的在结点上存储相关的信息,保证层数尽量的少,以便后面我们可以更快的找到信息,磁盘的I/O操作也少一些,而且B类树是平衡树,每个结点到叶子结点的高度都是相同,这也保证了每个查询是稳定的。
- 总的来说,B/B+树是为了磁盘或其它存储设备而设计的一种平衡多路查找树(相对于二叉,B树每个内节点有多个分支),与红黑树相比,在相同的的节点的情况下,一颗B/B+树的高度远远小于红黑树的高度(在下面B/B+树的性能分析中会提到)。B/B+树上操作的时间通常由存取磁盘的时间和CPU计算时间这两部分构成,而CPU的速度非常快,所以B树的操作效率取决于访问磁盘的次数,关键字总数相同的情况下B树的高度越小,磁盘I/O所花的时间越少。
B+树的插入删除
- https://www.cnblogs.com/nullzx/p/8729425.html
为什么说B+树比B树更适合数据库索引
- B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。
- B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
- 由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。
JVM内存配置参数
- -Xmx Java Heap最大值,默认值为物理内存的1/4,最佳设值应该视物理内存大小及计算机内其他内存开销而定;
- -Xms Java Heap初始值,Server端JVM最好将-Xms和-Xmx设为相同值,开发测试机JVM可以保留默认值;
- -Xmn Java Heap Young区大小,不熟悉最好保留默认值;
- -Xss 每个线程的Stack大小,不熟悉最好保留默认值;
extends 抽象类和 interface 区别 (*)
- 接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。
- 接口中的方法定义默认为 public abstract 类型,接口中的成员变量类型默认为 public static final
- 抽象类可以有构造方法,接口中不能有构造方法。
- 抽象类中可以有普通成员变量,接口中没有普通成员变量。
- 抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
- 抽象类中的抽象方法的访问类型可以是public,protected,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
- 抽象类中可以包含静态(static)方法,接口中不能包含静态(static)方法。
- 抽象类和接口中都可以包含静态成员变量(static),抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
- 一个类只能继承一个抽象类,但是可以实现多个接口。
- 一个接口可以继承多个接口。
- 抽象类所体现的是一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在”is-a”关系关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上是一致的,仅仅是实现了接口定义的契约而已,是”like-a”的关系。
Servlet生命周期
- 调用 init() 方法初始化
- 调用 service() 方法来处理客户端的请求
- 调用 destroy() 方法释放资源,标记自身为可回收
- 被垃圾回收器回收
Cookie, Session区别
- cookie数据存放在客户的浏览器上,session数据放在服务器上
- cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session
- session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE
- 单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。
非对称加密,对称加密 对称加密(Symmetric Cryptography),又称私钥加密
- 对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key),这种方法在密码学中叫做对称加密算法。对称加密有很多种算法,由于它效率很高,所以被广泛使用在很多加密协议的核心当中。对称加密通常使用的是相对较小的密钥,一般小于256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。如果你只用1 bit来做这个密钥,那黑客们可以先试着用0来解密,不行的话就再用1解;但如果你的密钥有1 MB大,黑客们可能永远也无法破解,但加密和解密的过程要花费很长的时间。密钥的大小既要照顾到安全性,也要照顾到效率,是一个trade-off。
非对称加密(Asymmetric Cryptography),又称公钥加密
- 1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。相对于“对称加密算法”这种方法也叫做“非对称加密算法”。非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。比如,你向银行请求公钥,银行将公钥发给你,你使用公钥对消息加密,那么只有私钥的持有人--银行才能对你的消息解密。与对称加密不同的是,银行不需要将私钥通过网络发送出去,因此安全性大大提高。
目前通信安全的方法
- 将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。
Http, Https 区别 (*)
- Http协议运行在TCP之上,明文传输,客户端与服务器端都无法验证对方的身份;Https是身披SSL(Secure Socket Layer)外壳的Http,运行于SSL上,SSL运行于TCP之上,是添加了加密和认证机制的HTTP。
二者之间存在如下不同:
- 端口不同:Http与Http使用不同的连接方式,用的端口也不一样,前者是80,后者是443;
- 资源消耗:和HTTP通信相比,Https通信会由于加减密处理消耗更多的CPU和内存资源;
- 开销:Https通信需要证书,而证书一般需要向认证机构购买;
- Https的加密机制是一种共享密钥加密和公开密钥加密并用的混合加密机制。SSL协议是通过非对称密钥机制保证双方身份认证,并完成建立连接,在实际数据通信时通过对称密钥机制保障数据安全性.
长连接,短连接
- http://www.cnblogs.com/0201zcr/p/4694945.html
- connection:keep-alive
短连接
- 模拟一下TCP短连接的情况: client 向 server 发起连接请求 server 接到请求,双方建立连接 client 向 server 发送消息 server 回应 client 一次读写完成,此时双方任何一个都可以发起 close 操作 在第 5 点钟,一般都是 client 先发起 close 操作。因为一般的 server 不会回复完 client 后就立即关闭连接。 当然也不排除有特殊的情况。 从上面的描述看,短连接一般只会在 client/server 间传递一次读写操作
- 管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段
长连接
- 再模拟一下长连接的情况: client 向 server 发起连接 server 接到请求,双方建立连接 client 向 server 发送消息 server 回应 client 一次读写完成,连接不关闭 后续读写操作… 需要TCP保活功能。
应用场景
- 长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。 每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接, 再操作的话那么处理速度会降低很多,所以每个操作完后都不断开, 再次处理时直接发送数据包就OK了,不用建立TCP连接。 例如:数据库的连接用长连接,如果用短连接频繁的通信会造成socket错误, 而且频繁的socket 创建也是对资源的浪费。
- 而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源, 如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话, 那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。
三次握手,四次挥手(*) 常问问题, 熟背
为什么是三次握手不是两次握手
- 在只有两次“握手”的情形下,假设Client想跟Server建立连接,但是却因为中途连接请求的数据报丢失了,故Client端不得不重新发送一遍;这个时候Server端仅收到一个连接请求,因此可以正常的建立连接。但是,有时候Client端重新发送请求不是因为数据报丢失了,而是有可能数据传输过程因为网络并发量很大在某结点被阻塞了,这种情形下Server端将先后收到2次请求,并持续等待两个Client请求向他发送数据…问题就在这里,Cient端实际上只有一次请求,而Server端却有2个响应,极端的情况可能由于Client端多次重新发送请求数据而导致Server端最后建立了N多个响应在等待,因而造成极大的资源浪费
为什么是四次挥手
- 双向通信
- 假如现在你是客户端你想断开跟Server的所有连接该怎么做?第一步,你自己先停止向Server端发送数据,并等待Server的回复。但事情还没有完,虽然你自身不往Server发送数据了,但是因为你们之前已经建立好平等的连接了,所以此时他也有主动权向你发送数据;故Server端还得终止主动向你发送数据,并等待你的确认
GET POST区别
- 在客户端, Get 方式在通过 URL 提交数据,数据 在URL中可以看到;POST方式,数据放置在HTML HEADER内提交。
- GET方式提交的数据最多只能有1024字节,而POST则没有此限制。
- 安全性问题。使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get ;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post 为好。
- 安全的和幂等的。所谓安全的意味着该操作用于获取信息而非修改信息。幂等的意味着对同一 URL 的多个请求应该返回同样的结果。完整的定义并不像看起来那样严格。换句话说, GET 请求一般不应产生副作用。从根本上讲,其目标是当用户打开一个链接时,她可以确信从自身的角度来看没有改变资源。比如,新闻站点的头版不断更新。虽然第二次请求会返回不同的一批新闻,该操作仍然被认为是安全的和幂等的,因为它总是返回当前的新闻。反之亦然。POST 请求就不那么轻松了。 POST 表示可能改变服务器上的资源的请求。仍然以新闻站点为例,读者对文章的注解应该通过 POST 请求实现,因为在注解提交之后站点已经不同了(比方说文章下面出现一条注解)。
TCP UDP区别 (*)
- TCP是面向连接的,UDP是无连接的;
- TCP是可靠的,UDP是不可靠的;
- TCP只支持点对点通信,UDP支持一对一、一对多、多对一、多对多的通信模式;
- TCP是面向字节流的,UDP是面向报文的;
- TCP有拥塞控制机制;UDP没有拥塞控制,适合媒体通信;
- TCP首部开销(20个字节)比UDP的首部开销(8个字节)要大;
从输入网址到获得页面的过程
- (1). 浏览器查询DNS,获取域名对应的IP地址:具体过程包括浏览器搜索自身的DNS缓存、搜索操作系统的DNS缓存、读取本地的Host文件和向本地DNS服务器进行查询等。对于向本地DNS服务器进行查询,如果要查询的域名包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析(此解析具有权威性);如果要查询的域名不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析(此解析不具有权威性)。如果本地域名服务器并未缓存该网址映射关系,那么将根据其设置发起递归查询或者迭代查询;
- (2). 浏览器获得域名对应的IP地址以后,浏览器向服务器请求建立链接,发起三次握手;
- (3). TCP/IP链接建立起来后,浏览器向服务器发送HTTP请求;
- (4). 服务器接收到这个请求,并根据路径参数映射到特定的请求处理器进行处理,并将处理结果及相应的视图返回给浏览器;
- (5). 浏览器解析并渲染视图,若遇到对js文件、css文件及图片等静态资源的引用,则重复上述步骤并向服务器请求这些资源;
- (6). 浏览器根据其请求到的资源、数据渲染页面,最终向用户呈现一个完整的页面。
OSI网络体系结构与TCP/IP协议模型 (*)
物理层
- 实现了相邻计算机节点之间比特流的透明传送,并尽可能地屏蔽掉具体传输介质和物理设备的差异,使其上层(数据链路层)不必关心网络的具体传输介质
数据链路层
- 接收来自物理层的位流形式的数据,并封装成帧,传送到上一层;同样,也将来自上层的数据帧,拆装为位流形式的数据转发到物理层。这一层在物理层提供的比特流的基础上,通过差错控制、流量控制方法,使有差错的物理线路变为无差错的数据链路,即提供可靠的通过物理介质传输数据的方法。
网络层
- 将网络地址翻译成对应的物理地址,并通过路由选择算法为分组通过通信子网选择最适当的路径.
传输层
- 在源端与目的端之间提供可靠的透明数据传输,使上层服务用户不必关系通信子网的实现细节。在协议栈中,传输层位于网络层之上,传输层协议为不同主机上运行的进程提供逻辑通信,而网络层协议为不同主机提供逻辑通信,如下图所示.
会话层
- 会话层是OSI模型的第五层,是用户应用程序和网络之间的接口,负责在网络中的两节点之间建立、维持和终止通信.
表示层
- 数据的编码,压缩和解压缩,数据的加密和解密.
应用层
- 用户的应用进程提供网络通信服务.
TCP和UDP分别对应的常见应用层协议 TCP
- FTP,
- Telnet,
- SMTP,
- POP3,
- HTTP
UDP
- DNS
- SNMP(简单网络管理协议,使用161号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势)
- TFTP(Trival File Transfer Protocal):简单文件传输协议,该协议在熟知端口69上使用UDP服务。
网络层的ARP协议工作原理
- 网络层的ARP协议完成了IP地址与物理地址的映射。首先,每台主机都会在自己的ARP缓冲区中建立一个ARP列表,以表示IP地址和MAC地址的对应关系。当源主机需要将一个数据包要发送到目的主机时,会首先检查自己ARP列表中是否存在该IP地址对应的MAC地址:如果有,就直接将数据包发送到这个MAC地址;如果没有,就向本地网段发起一个ARP请求的广播包,查询此目的主机对应的MAC地址。此ARP请求数据包里包括源主机的IP地址、硬件地址、以及目的主机的IP地址。网络中所有的主机收到这个ARP请求后,会检查数据包中的目的IP是否和自己的IP地址一致。如果不相同就忽略此数据包;如果相同,该主机首先将发送端的MAC地址和IP地址添加到自己的ARP列表中,如果ARP表中已经存在该IP的信息,则将其覆盖,然后给源主机发送一个ARP响应数据包,告诉对方自己是它需要查找的MAC地址;源主机收到这个ARP响应数据包后,将得到的目的主机的IP地址和MAC地址添加到自己的ARP列表中,并利用此信息开始数据的传输。如果源主机一直没有收到ARP响应数据包,表示ARP查询失败。
HTTP常见状态码
- 1×× : 请求处理中,请求已被接受,正在处理
- 2×× : 请求成功,请求被成功处理
- 200 OK
- 3×× : 重定向,要完成请求必须进行进一步处理
- 301 : 永久性转移
- 302 :暂时性转移
- 304 : 已缓存
- 4×× : 客户端错误,请求不合法
- 400:Bad Request,请求有语法问题
- 403:拒绝请求
- 404:客户端所访问的页面不存在
- 5×× : 服务器端错误,服务器不能处理合法请求
- 500 :服务器内部错误
- 503 : 服务不可用,稍等
HTTP协议是无状态的 和 Connection: keep-alive的区别
- HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。
- 从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。
- Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间
属于网络112.10.200.0/21的地址是? (*) 笔试常考
- 前21位为网络地址,后12位为主机地址。112 对应前8位,10对应第二个8位,因此200对应第3个8位又200的二进制表示为1100 1000 前面已经有了16位,因此11001 是属于网络地址的。000是属于主机地址 那么,最大的地址为【112(十进制)】【10(十进制)】【11001 111】【 11111111】转换为十进制为112.10.207.255 故网络的地址范围为: 112.10.200.0~112.10.207.255
某一速率为100M的交换机有20个端口,其一个端口上连着一台笔记本电脑,此电脑从迅雷上下载一部1G的电影需要的时间可能是多久?
- 1GB/(100Mb/s ÷8,字节→比特)=81.92 s, 比81s大
- 交换机在同一时刻可进行多个端口对之间的数据传输。每一端口都可视为独立的网段,连接在其上的网络设备独自享有全部的带宽,无须同其他设备竞争使用。
与10.110.12.29 mask 255.255.255.224属于同一网段的主机IP地址是?(*) 笔试常考
- 通俗理解: 子网掩码为255.255.255.224=255.255.255.11100000,也就是讲第四个字节,有三位用来表示子网号(共有000,001,010….111等8个子网号) 请看题目给的是:10.110.12.29=10.110.12.29=10.110.12.00011101,从这里看,题目给出的IP所处子网号在000段,所以跟这个IP在一个网段的IP的前27位是定的:10.110.12.000 最后5位可以是00001~11110(全0和全1是不行的),也就是讲IP范围为 10.110.12.00000000~ 10.110.12.00011110
数据在计算机网络中的称法?
- 应用层:报文
- 运输层:报文段/用户数据报
- 网际层:IP数据报/分组/包
- 数据链路层:帧
- 物理层:比特流
try catch finally (*) 笔试常见套路题
- https://blog.csdn.net/aaoxue/article/details/8535754
OOM, Out of Memory 错误
常见OOM情况
- Java堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改。
- Java永久代溢出,即方法区溢出了,一般出现于大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。
- java.lang.StackOverflowError, 不会抛OOM error,但也是比较常见的Java内存溢出。JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。
- 静态集合类
常用Linux命令
cd
- cd /root/Docements # 切换到目录/root/Docements
- cd ./path # 切换到当前目录下的path目录中,“.”表示当前目录
- cd ../path # 切换到上层目录中的path目录中,“..”表示上一层目录
ls
- -l :列出长数据串,包含文件的属性与权限数据等
- -a :列出全部的文件,连同隐藏文件(开头为.的文件)一起列出来(常用)
- -d :仅列出目录本身,而不是列出目录的文件数据
- -h :将文件容量以较易读的方式(GB,kB等)列出来
- -R :连同子目录的内容一起列出(递归列出),等于该目录下的所有文件都会显示出来
grep 命令常用于分析一行的信息,若当中有我们所需要的信息,就将该行显示出来,该命令通常与管道命令一起使用,用于对一些命令的输出进行筛选加工等等
- grep [-acinv] [--color=auto] '查找字符串' filename
- -a :将binary文件以text文件的方式查找数据
- -c :计算找到‘查找字符串’的次数
- -i :忽略大小写的区别,即把大小写视为相同
- -v :反向选择,即显示出没有‘查找字符串’内容的那一行
find 寻找 find [PATH] [option] [action] 与时间有关的参数:
- -mtime n : n为数字,意思为在n天之前的“一天内”被更改过的文件;
- -mtime +n : 列出在n天之前(不含n天本身)被更改过的文件名;
- -mtime -n : 列出在n天之内(含n天本身)被更改过的文件名;
- -newer file : 列出比file还要新的文件名
cp 复制
- -a :将文件的特性一起复制
- -p :连同文件的属性一起复制,而非使用默认方式,与-a相似,常用于备份
- -i :若目标文件已经存在时,在覆盖时会先询问操作的进行
- -r :递归持续复制,用于目录的复制行为
- -u :目标文件与源文件有差异时才会复制
mv 移动
- -f :force强制的意思,如果目标文件已经存在,不会询问而直接覆盖
- -i :若目标文件已经存在,就会询问是否覆盖
- -u :若目标文件已经存在,且比目标文件新,才会更新
rm 删除
- -f :就是force的意思,忽略不存在的文件,不会出现警告消息
- -i :互动模式,在删除前会询问用户是否操作
- -r :递归删除,最常用于目录删除,它是一个非常危险的参数
ps 查看进程
- -A :所有的进程均显示出来
- -a :不与terminal有关的所有进程
- -u :有效用户的相关进程
- -x :一般与a参数一起使用,可列出较完整的信息
- -l :较长,较详细地将PID的信息列出
- ps aux # 查看系统所有的进程数据
- ps ax # 查看不与terminal有关的所有进程
- ps -lA # 查看系统所有的进程数据
- ps axjf # 查看连同一部分进程树状态
kill 该命令用于向某个工作(%jobnumber)或者是某个PID(数字)传送一个信号,它通常与ps和jobs命令一起使用,它的基本语法如下:kill -signal PID
- 1:SIGHUP,启动被终止的进程
- 2:SIGINT,相当于输入ctrl+c,中断一个程序的进行
- 9:SIGKILL,强制中断一个进程的进行
- 15:SIGTERM,以正常的结束进程方式来终止进程
- 17:SIGSTOP,相当于输入ctrl+z,暂停一个进程的进行
killall
- -i :交互式的意思,若需要删除时,会询问用户
- -e :表示后面接的command name要一致,但command name不能超过15个字符
- -I :命令名称忽略大小写 例如:
- killall -SIGHUP syslogd # 重新启动syslogd
file 用于判断接在file命令后的文件的基本数据,因为在Linux下文件的类型并不是以后缀为分的
- file filename
例如: file ./test
tar
- -c :新建打包文件
- -t :查看打包文件的内容含有哪些文件名
- -x :解打包或解压缩的功能,可以搭配-C(大写)指定解压的目录,注意-c,-t,-x不能同时出现在同一条命令中
- -j :通过bzip2的支持进行压缩/解压缩
- -z :通过gzip的支持进行压缩/解压缩
- -v :在压缩/解压缩过程中,将正在处理的文件名显示出来
- -f filename :filename为要处理的文件
- -C dir :指定压缩/解压缩的目录dir 常用tar命令
- 压缩:tar -jcv -f filename.tar.bz2 要被处理的文件或目录名称
- 查询:tar -jtv -f filename.tar.bz2
- 解压:tar -jxv -f filename.tar.bz2 -C 欲解压缩的目录
cat 用于查看文本文件的内容,后接要查看的文件名,通常可用管道与more和less一起使用,从而可以一页页地查看数据
- cat text | less # 查看text文件中的内容 注:这条命令也可以使用less text来代替
chgrp 改变文件所属所属用户组
- chgrp [-R] dirname/filename
- -R :进行递归的持续对所有文件和子目录更改
例如:
- chgrp users -R ./dir # 递归地把dir目录下中的所有文件和子目录下所有文件的用户组修改为users
chown 改变文件所有者
chmod 改变文件权限
- chmod [-R] xyz 文件或目录
- -R:进行递归的持续更改,即连同子目录下的所有文件都会更改
vim
JVM类加载机制 (*)
面试有概率会问
加载
- 加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的入口。注意这里不一定非得要从一个Class文件获取,这里既可以从ZIP包中读取(比如从jar包和war包中读取),也可以在运行时计算生成(动态代理),也可以由其它文件生成(比如将JSP文件转换成对应的Class类)。
验证
- 这一阶段的主要目的是为了确保Class文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
准备
- 准备阶段是正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量所使用的内存空间。注意这里所说的初始值概念,比如一个类变量定义为: public static int v = 8080; 实际上变量v在准备阶段过后的初始值为0而不是8080,将v赋值为8080的putstatic指令是程序被编译后,存放于类构造器方法之中,这里我们后面会解释。 但是注意如果声明为: public static final int v = 8080; 在编译阶段会为v生成ConstantValue属性,在准备阶段虚拟机会根据ConstantValue属性将v赋值为8080。
解析
- 解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是class文件中的: CONSTANT_Class_info CONSTANT_Field_info CONSTANT_Method_info 等类型的常量。
符号引用和直接引用的概念:
- 符号引用与虚拟机实现的布局无关,引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。 直接引用可以是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在。
初始化
- 初始化阶段是类加载最后一个阶段,前面的类加载阶段之后,除了在加载阶段可以自定义类加载器以外,其它操作都由JVM主导。到了初始阶段,才开始真正执行类中定义的Java程序代码。 初始化阶段是执行类构造器方法的过程。方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证方法执行之前,父类的方法已经执行完毕。p.s: 如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成()方法。
注意以下几种情况不会执行类初始化:
- 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。
- 定义对象数组,不会触发该类的初始化。
- 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。
- 通过类名获取Class对象,不会触发类的初始化。
- 通过Class.forName加载指定类时,如果指定参数initialize为false时,也不会触发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。
- 通过ClassLoader默认的loadClass方法,也不会触发初始化动作。
给你一个未知长度的链表,怎么找到中间的那个节点? 快慢指针,快指针走两步,慢指针走一步,快指针到尾了,慢指针走到一半。
类加载器 (*)
面试必考
虚拟机设计团队把加载动作放到JVM外部实现,以便让应用程序决定如何获取所需的类,JVM提供了3种类加载器:
- 启动类加载器(Bootstrap ClassLoader):负责加载 JAVA_HOMElib 目录中的,或通过-Xbootclasspath参数指定路径中的,且被虚拟机认可(按文件名识别,如rt.jar)的类。
- 扩展类加载器(Extension ClassLoader):负责加载 JAVA_HOMElibext 目录中的,或通过java.ext.dirs系统变量指定路径中的类库。
- 应用程序类加载器(Application ClassLoader):负责加载用户路径(classpath)上的类库。
- JVM通过双亲委派模型进行类的加载,当然我们也可以通过继承java.lang.ClassLoader实现自定义的类加载器。
- 当一个类加载器收到类加载任务,会先交给其父类加载器去完成,因此最终加载任务都会传递到顶层的启动类加载器,只有当父类加载器无法完成加载任务时,才会尝试执行加载任务。
- 采用双亲委派的一个好处是比如加载位于rt.jar包中的类java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个Object对象。
访问权限
- 对于外部类来说,只有两种修饰,public和默认(default),因为外部类放在包中,只有两种可能,包可见和包不可见。
- 对于内部类来说,可以有所有的修饰,因为内部类放在外部类中,与成员变量的地位一致,所以有四种可能。
Spring bean 范围
- singleton, prototype, request, session, global session
进程间的通信方式,线程间的通信方式 进程
- 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
- 有名管道 (namedpipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
- 信号量(semophore ) :信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
- 消息队列( messagequeue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
- 信号 (sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
- 共享内存(shared memory ):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
- 套接字(socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
线程
- 锁机制:包括互斥锁、条件变量、读写锁
- 互斥锁提供了以排他方式防止数据结构被并发修改的方法。
- 读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
- 条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。while+if+volatile变量
- 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
- 信号机制(Signal):类似进程间的信号处理
Java线程
- synchoronized
- wait/notify
- lock condition
- semaphore
- countdownlatch
- cyclicbarrier
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。
MyBatis中#{}和
- #{}是经过预编译的,是安全的,而
{}是未经过预编译的,仅仅是取变量的值,是非安全的,存在sql注入。
- 只能${}的情况,order by、like 语句只能用${}了,用#{}会多个' '导致sql语句失效.此外动态拼接sql也要用不能识别此Latex公式: {}
- #{} 这种取值是编译好SQL语句再取值, {} 这种是取值以后再去编译SQL语句
重要:接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的sql注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。
数据库数据不一致的原因
- 数据冗余
如果数据库中存在冗余数据,比如两张表中都存储了用户的地址,在用户的地址发生改变时,如果只更新了一张表中的数据,那么这两张表中就有了不一致的数据。
- 并发控制不当
比如某个订票系统中,两个用户在同一时间订同一张票,如果并发控制不当,可能会导致一张票被两个用户预订的情况。当然这也与元数据的设计有关。
- 故障和错误
如果软硬件发生故障造成数据丢失等情况,也可能引起数据不一致的情况。因此我们需要提供数据库维护和数据恢复的一些措施。
线程的状态(*)
笔试常考
- 新建( new ):新创建了一个线程对象。
- 可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象 的 start ()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获 取 cpu 的使用权 。
- 运行( running ):可运行状态( runnable )的线程获得了 cpu 时间片( timeslice ) ,执行程序代码。
- 阻塞( block ):阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice,暂时停止运行。直到线程进入可运行( runnable )状态,才有 机会再次获得 cpu timeslice 转到运行( running )状态。阻塞的情况分三种: (一). 等待阻塞:运行( running )的线程执行 o . wait ()方法, JVM 会把该线程放 入等待队列(waitting queue )中。 (二). 同步阻塞:运行( running )的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线程放入锁池( lock pool )中。 (三). 其他阻塞: 运行( running )的线程执行Thread . sleep ( long ms )或 t . join ()方法,或者发出了 I / O 请求时, JVM会把该线程置为阻塞. 当 sleep ()状态超时、 join ()等待线程终止或者超时、或者 I / O 处理完毕时,线程重新转入可运行( runnable )状态。
- 死亡( dead ):线程 run ()、 main () 方法执行结束,或者因异常退出了 run ()方法,则该线程结束生命周期。死亡的线程不可再次复生。
如何确保N个线程可以访问N个资源同时又不导致死锁?
多线程产生死锁需要四个条件,分别是互斥性,保持和请求,不可剥夺性还有要形成闭环,这四个条件缺一不可,只要破坏了其中一个条件就可以破坏死锁,其中最简单的方法就是线程都是以同样的顺序加锁和释放锁,也就是破坏了第四个条件。
背包问题(*) 试题描述:小明喜欢在火车旅行的时候用手机听音乐,他有N首歌在手机里,在整个火车途中,他可以听P首歌,所以他想产生一个播放表产生P首歌曲,这个播放表的原则是:
(1)每首歌都要至少被播放一次
(2)在两首一样的歌中间,至少有N首其他的歌
小明想有多少种不同的播放表可以产生,那么给你N、M、P,你来算一下,输出结果取1000000007的余数。
- 定义 value(i,j) 为在背包装载体积为 i,物品为第 1 到 j 个的情况下,背包的最大价值 value(v,sum(m[i])) 即为所求 可以把空间复杂度从 O(nv) 降到 O(v) 状态转移方程: value(i,j) = |-> max(value(i-w[j],j-1)+s[j],value(i-1,j-1) (i-w[j] >= 0) |-> value(i-1,j-1) (i-w[j] < 0)
进程,线程区别
- 1)含义 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
- 2)区别 (1)一个程序至少有一个进程,一个进程至少有一个线程. (2)线程的划分尺度小于进程,使得多线程程序的并发性高。 (3)进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 (4)线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 (5)从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。
int cast到byte(*) 笔试题
public class leftshift_operator {
public static void main(String args[]){
byte x = 64;
int i;
byte y;
i = x<<2;
y = (byte)(x<<2);
System.out.print(i+ " " +y);
}
}
- 输出 256 0
- 0是因为 x 01000000 被 cast 到 int 32位 00000000000000000000000001000000 左移2位 00000000000000000000000100000000, 最低8位 00000000
CMS缺点
- CMS收集器对CPU资源非常敏感 在并发阶段,虽然不会导致用户线程停顿,但是会因为占用了一部分线程使应用程序变慢,总吞吐量会降低,为了解决这种情况,虚拟机提供了一种“增量式并发收集器” 的CMS收集器变种, 就是在并发标记和并发清除的时候让GC线程和用户线程交替运行,尽量减少GC 线程独占资源的时间,这样整个垃圾收集的过程会变长,但是对用户程序的影响会减少。(效果不明显,不推荐)
- CMS处理器无法处理浮动垃圾 CMS在并发清理阶段线程还在运行, 伴随着程序的运行自然也会产生新的垃圾,这一部分垃圾产生在标记过程之后,CMS无法再当次过程中处理,所以只有等到下次gc时候在清理掉,这一部分垃圾就称作“浮动垃圾”
- CMS是基于“标记--清除”算法实现的,所以在收集结束的时候会有大量的空间碎片产生。空间碎片太多的时候,将会给大对象的分配带来很大的麻烦,往往会出现老年代还有很大的空间剩余,但是无法找到足够大的连续空间来分配当前对象的,只能提前触发full gc。
- 需要更大的堆空间
++操作符和乘除 下列代码执行后的变量num3的值?
public static void main(String[] args) {
int num1 = 6, num2 = 7, num3 = 12;
if (++num1 == num2)
num3 = ++num3 * 3;
System.out.println(num3);
}
- 39, 先++num3 ,再乘3
某网络的IP地址空间为10.0.17.0/24,采用等长子网划分,子网掩码为255.255.255.240,则该网络的最大子网个数、每个子网内的最大分配地址个数?(*) 笔试常考
- 240, 11110000
- 2^4=16 最大子网个数
- 2^4-2=14 子网最大分配地址个数
Class, newInstance, 默认构造器
public class whatTheHell {
public whatTheHell() {
}
private String a;
private Integer b;
public whatTheHell(String a, Integer b) {
this.a = a;
this.b = b;
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public Integer getB() {
return b;
}
public void setB(Integer b) {
this.b = b;
}
public static void main(String[] args) {
Class whatTheHellClass = whatTheHell.class;
try {
whatTheHell whatTheHell = whatTheHellClass.newInstance();
System.out.println(whatTheHell == null ? true : false);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
- 不提供默认构造器会报错。
若用一个大小为6的数组来实现循环队列,且当前rear和front的值分别0和3。当从队列中删除一个元素,再加入两 个元素后,rear和front的值分别为?
- 2,4
- 删除一个元素后,队首指针要加1,front=(front+1)%6,结果为4,每加入一个元素队尾指针加一,即real=(real+1)%6,加入两个元素后变为2
棵完全二叉树有600个节点,那么它的叶子节点有
- (600+1)/2=300
this, super
- this()函数主要应用于同一类中从某个构造函数调用另一个重载版的构造函数。this()只能用在构造函数中,并且也只能在第一行。所以在同一个构造函数中this()和super()不能同时出现。
- super()函数在子类构造函数中调用父类的构造函数时使用,而且必须要在构造函数的第一行
java中,当实例化子类对象时,如果有以下几个会被加载,那么加载的顺序是什么?(*) 笔试常考
- (1)父类静态代码块
- (2)子类静态代码块
- (3)父类非静态代码块
- (4)父类构造函数
- (5)子类非静态代码块
- (6)子类构造函数
设在一棵度数为3的树中,度数为3的结点数有2个,度数为2的结点数有1个,度数为1的结点数有2个,那么度数为0的结点数有( )个?
- 顶点数 = 所有节点度数 +1
- 2+1+2+x = (3x2 + 2x1 + 1x2 + 0 x X) + 1
- x = 6
forward和redirect区别
- 直接转发方式(Forward),客户端和浏览器只发出一次请求,Servlet、HTML、JSP或其它信息资源,由第二个信息资源响应该请求,在请求对象request中,保存的对象对于每个信息资源是共享的。
- 间接转发方式(Redirect)实际是两次HTTP请求,服务器端在响应第一次请求的时候,让浏览器再向另外一个URL发出请求,从而达到转发的目的。
- redirect 默认302暂时跳转
操作系统,临时抱佛脚
- https://blog.csdn.net/csdn_chai/article/details/78002202
- https://zhuanlan.zhihu.com/p/23755202
前缀(波兰),后缀(逆波兰),中缀表达式
- https://blog.csdn.net/antineutrino/article/details/6763722
BigInteger, BigDecimal
- https://blog.csdn.net/zhongkelee/article/details/52289163
在一个C类地址段内,需要将网络划分为 7个子网,每个子网有15个主机,则可以使用哪个子网掩码?(*)
- 255.255.255.224
- IP地址的结构是:网络号+主机号, 划分子网是从主机号中抽取几位进行子网划分,c类地址前24位为网络号
- 224, 11100000
- 2^3=8>7
- 2^5=32>15
Linux 网络相关命令
- ping是使用的ICMP协议,是IP层协议,但是端口是应用层的,所以它只能判断能够访问ip,不能判断端口
- ifconfig是查看本机的网络设置,IP,子网掩码等
- telnet是应用层的,可以判端口访问情况
- netstat显示网络信息,如网络连接,路由表,接口状态
递归时间复杂度 master 公式 T(N) = a*T(N/b) + O(N^d)
估计递归问题复杂度的通式,只要复杂度符合以下公式,都可以套用此公式计算时间复杂度
例子:递归方式查找数组最大值 T(N) = 2*T(N/2) + O(1)
T(N):样本量为 N 的情况下,时间复杂度 N:父问题的样本量 a:子问题发生的次数(父问题被拆分成了几个子问题,不需要考虑递归调用,只考虑单层的父子关系) b:被拆成子问题,子问题的样本量(子问题所需要处理的样本量),比如 N 被拆分成两半,所以子问题样本量为 N/2 O(N^d):剩余操作的时间复杂度,除去调用子过程之外,剩下问题所需要的代价(常规操作则为 O(1))
- log(b,a) > d -> 复杂度为O(N^log(b,a))
- log(b,a) = d -> 复杂度为O(N^d * logN)
- log(b,a) < d -> 复杂度为O(N^d)
Java变量命名(*)
- $, _, 字母开头
- 不能是数字开头
- 不能使关键字private, final…
查看linux操作系统磁盘空间命令
- df
设有一个含有13个元素的Hash表(0~12),Hash函数是:H(key)=key % 13,其中%是求余数运算。用线性探查法解决冲突,则对于序列(2、8、31、20、19、18、53、27),18应放在第几号格中?
- 求出18之前的序列余数为2、8、5、7、6,H(18)=5与之前的冲突,直接向后移,6、7、8都有元素,因此放在9号上
如果一个二叉树中任意节点的左右子树“高度”相差不超过 1,我们称这个二叉树为“高度平衡二叉树”。根据如上定义,一个高度为 8 的高度平衡二叉树至少有几个节点?
- 54
- 类似斐波那契数列的递推公式。Sn = Sn-1 + Sn-2 + 1,初值,S1 =1,S2 =2
- 1 2 4 7 12 20 33 54
某公司申请到一个C类IP地址,但要连接6个的子公司,最大的一个子公司有 26台计算机,每个子公司在一个网段中,则子网掩码应设为?(*)
- 11111111.11111111.11111111.?
- 2^3=8, 至少3个1
- 2^5=32, 32-网关-广播=30>26
- 11100000
- 224
- 255.255.255.224
以下出自:乔戈里 链接:2019年校招,你经历了什么? 看了以后学到了很多
基础知识:
可以说掌握这个pdf上的知识,面试问的基础知识无处左右,我凭借这个pdf拿下了百度/秒针/去哪儿/华为/创新工厂/一点资讯等互联网公司的offer。
下文中截图来源于朋友一个pdf版本的面经,把所以知识点的答案整理了下来,耗费他将近至少1个月时间,在本文最后部分把这个pdf分享给大家,觉得有用的麻烦点赞关注走一波,谢谢!!!面经中有他的知识点的答案,如下图示例,非常详细!!!
1.数据结构与算法篇
你是java开发你就用java代码去实现,是C++开发就用C++去实现。
书籍参考:
(0)《图解算法》入门
(1)《剑指offer》 剑指Offer_编程题_牛客网
(2)《程序员代码面试指南 IT名企算法与数据结构题目最优解》参考左神视频
(3)leetcode LeetCode - The World’s Leading Online Programming Learning Platform
leedcode注意去英文官网,别去中国区,中国区讨论区讨论的少。
leedcode 注意一个tag一个tag的刷,例如动态规划,就把动态规划下的题目都刷了,基本刷个10多道,其它也基本有思路了,而且动态规划的题目笔试面试也常出。其次就是二叉树,链表,数组,回溯的题目。
(4)数据结构(严蔚敏)/大话数据结构 //如果觉得教材无聊就可以看大话系列
需要掌握的知识点:
数组、链表、二叉树、队列、栈的各种操作(性能,场景)
二分查找和各种变种的二分查找(循环有序数组找最大值最小值找n,有序数组找最左下标,最右下标)
各类排序算法以及复杂度分析(快排、归并、堆、冒泡、直接选择、插入排序)
各类算法题(手写)
理解并可以分析时间和空间复杂度。
动态规划(笔试回回有。。)、贪心。
红黑树、AVL树、Hash树、Tire树、B树、B+ 树(除了红黑树,其它要会插入删除查找,红黑树如果会更好,也算一个亮点)。
图算法(克鲁斯卡尔算法、普林母算法、迪克拉斯算法)
树的前序后序中序遍历的递归非递归实现,层次遍历,深度优先遍历,广度优先遍历递归与非递归实现
2.海量数据篇
教你如何迅速秒杀掉:99%的海量数据处理面试题 - WantFlyDaCheng的博客 - CSDN博客3.计算机网络篇
参考书籍:《图解http》《图解TCP/IP》《TCP/IP详解卷1》《计算机网络(谢希仁)》
知识点:
4.数据库篇
参考书籍:《高性能MySQL》 《MySQL技术内幕:InnoDB存储引擎(第2版)》
5.操作系统篇
参考书籍:
知识点:《操作系统精髓与设计原理(原书第6版)》
LRU会手写一个LRU的set与get的时间复杂度是o(1)的代码
6.Linux命令篇
参考书籍:《linux 鸟哥的私房菜》
7.安全加密
8.重头戏java篇
基础篇:
推荐书籍:《Java程序员面试笔试宝典-何昊》突击java面试的好书啊!!!
《写给大忙人看的JavaSE8》 《深入理解Java虚拟机:JVM高级特性与最佳实践》
《JAVA并发编程实战》《Java多线程编程核心技术》《java核心技术卷1》
1.基础篇:
2.集合篇:
3.锁
4.多线程
多看看《Java多线程编程核心技术》这块就没问题
5.jdk中的concurrent 俗称juc包
都要搞懂底层原理!!!
都要搞懂底层原理!!!
都要搞懂底层原理!!!
6.java虚拟机
主要看《深入理解java虚拟机》
7.设计模式
参考书籍:《大话设计模式》
知道每种设计模式是啥意思,可以手写一个单例模式,手写适配器模式,工厂模式,观察者模式,装饰器模式
知识点:
---------------------
8。框架知识
关注公众号:程序员乔戈里
以上面经是这个公众号,这份面经对我帮助很大,宣传一下。
在公众号后台回复 面经 就可以获取上面的pdf!
在公众号后台回复 面经 就可以获取上面的pdf!
在公众号后台回复 面经 就可以获取上面的pdf!
最后
创作不易,希望大家给个赞,推广Java公众号:程序员乔戈里
Python公众号:Python看世界
专注分享python/java求职面试/技术干货,使用python看世界等内容!
关注即送5T编程大礼包。无需转发点赞,直接送5T各个方向的资源~
并有我自己推荐的学习路线,需要的可以找我
Java学习比较难,建议数学基础好,逻辑思维能力好的朋友学习,最好有计算机专业基础。
学习Java的过程可能比较枯燥,但是学成未来将一片光明。
话不多说,小优为大家整理了一套Java学习路线,希望有所帮助:
1.JavaEE基础
- 基础语法:掌握Java当中的基本语法中的运算符、 数据类型以及相互转换和各种流程控 制语句、以及数组的使用
- 面向对象:建立面向对象的逻辑思维
- 核心类库、异常、集合、IO:掌握常用类当中的方法、String类 和包装类以及相互转换、异常的处理 方式、File类和使用io读取和输入数据 、深入理解常用集合类的用法、集合 的特点以及使用
- 线程、网络编程、反射、JDK1.8新特性:掌握多线程的概念、创建方式、同步 、通信、网络编程的基本概念、编写 、反射的应用以及jdk新特性的特点以 及应用方式
2.JavaWeb开发
- 前端技术:使用HTML、CSS进行前端界面的设 计、掌握对JavaScript、JQuery基本语 法的使用
- 数据库、JDBC&JDBCUtis:JDBC概述 JDBC使用步骤 Connection 、Statement、ResultSet接口 PreparedStatement对象 大数据处理 事务处理 隔离级别、DBCP、C3p0连 接池 DBUtis工具类
- XML、服务器&Servdet、JSP、AJAX:掌握XML的解析方式、掌握服务器的 概念以及其配置、熟悉Servlet开发规 范和相关概念、JSP基本原理、Session 和Cookie、过滤器和监听器的使用、 以及Ajax异步请求
- Struts:理解Struts的工作流程、并熟练操作数 据 、以及Struts在项目当中的应用、 商城项目数据库的设计、支付模块、 以及之间的业务关系
3.Java高级框架
- SpringMVC:理解SpringMVC的工作原理、并熟练 的应用
- Mybatis:掌握Mybatis开发环境的搭建、了解 Mybatis框架体系结构和原理、了解 ORM、以及Hibernate开发流程、 Hibernate与Mybatis的区别
- Spring:熟悉Spring模块结构和作用、掌握如何 对组件对象进行参数注入、掌握Spring 声明式事务处理、熟悉SSM框架整合 开发流程和规范
- Oracle、Linux&Redis &Nginx:掌握Oracle的安装存储过程、视图和 触发器的应用、Linux常用命令、掌握 Redis基本安装、命令、存储数据类型 、以及使用java操作Redis、掌握 Apache Nginx软件安装配置以及 Tomcat集群
- Maven:掌握Maven项目构建和管理、以及私 服的搭建流程
4.分布式项目实战
Git、SpringBoot:掌握Git基本使用、Github使用、git和 Eclipse的整合、了解SpringBoot框架 的结构和作用以及基本开发流程
学习Java一定要配合实战训练学习,在写的过程中发现问题,解决问题。
如果对于Java学习还有疑问,或者需要学习资料,可以找我哦~
算是入门Java的小白一个
起初就是傻傻的刷培训视频,动不动就是几十个小时的时间,后来觉着效率实在太低,速度太慢,遂停止
然后机缘巧合东查西找如获至宝,现在算是入门了Java,已经了解了Java的应用体系
先附上链接,再讲如何学习
How2J 的 Java教程路线图如下
方法:看教程实操+不懂了看视频手把手演示学习
- 能看懂直接实践,不需要去刷时间很长过分细致的冗余视频
- 看不懂的地方,每个教程本站配有视频讲解,可以再看视频听站长的细心讲解
以Java基础举例
- 进入Java基础章节,可以看到是一个个小的学习块,并且记录着你的学习进度
2. 点进某一个学习块,按顺序记录着本学习块的内容,循序渐进,先有文字讲解学习内容,真的如果自己理解能力较差,可以点击视频链接,有手把手的演示教程,包教包会,而且作为一个站长一直更新项目,维护内容的学习站,本站内容很新,教学内容也很有趣,以LOL里面的物品英雄等为例,让人不由自主的看过去(适度游戏,切勿沉迷。。。)
3. 然后可以去学习路线中,有两种走法
- 由始至终:求职者等面试需要,急切的需要一些项目经验的,本站的精品电商平台项目也是相当给力的,直接点击项目,直接看想做这个项目需要的知识点,然后就:开学!!
- 循序渐进:学生等不太着急,时间较为充分的,可以走这一条路线,学习了前面的才能点亮后面的知识点,一点点学习,稳扎稳打,打牢基础
其他补充
- 学习站收录的很多学习问题,站长也会回复,(站长是活人!!项目问题都会解答而且有交流群可以直接联系站长大大)
- 待补充。。。。。
再附上链接以及硬核给力项目链接,到这里,不用我教,你也就已经知道怎么去安排Java的学习了
How2J 的 Java教程天猫前端系列教材 (一)- 基础 - 前端练手项目-先定一个小目标,做他一个天猫官网JAVA WEB 项目教程-模精品天猫整站 J2EE版一本糊涂账系列教材 (一)- 基础 - 项目简介java 练习题,共计 194 道Hibernate系列教材 (一)- 基础 - hibernate 基于实例的入门教程Struts系列教材 (一)- 基础 - 教程SSH系列教材 (一)- 整合Struts+Spring+Hibernate 逐一配置的步骤Mybatis系列教材 (一)- 基础 - 入门教程Spring MVC系列教材 (一)- 教程还有许多“玩法”,自己进去探索吧~
附上自己的咸鱼博客,欢迎来踩Hz's blog