JAVA基础
反射
-
类对象
定义:所有的类,都存在一个类对象,这个类对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。
获取类对象的方法:1.Class.forName(类名); 2.类名.class; 3.对象.getClass()
注意:获取类对象时,会导致静态属性被初始化 -
通过反射创建对象
通过反射获取类对象 => 由类对象获得构造器对象 => 由构造器对象创建新对象//使用反射的方式创建对象 String className = "charactor.Hero"; //类对象 Class pClass=Class.forName(className); //构造器 Constructor c= pClass.getConstructor(); //通过构造器实例化 Hero h2= (Hero) c.newInstance(); h2.name="gareen";
-
通过反射访问/修改对象属性
通过getField或者getDeclaredField获取字段对象,区别在于:
1.getField 只能获取public的,包括从父类继承来的字段;
2.getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。 (注: 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true)) -
通过反射调用对象的方法
getMethod获取方法…m.invoke(对象) -
反射的作用
参考:反射机制,有什么用
注解
- 基本内置注解
@Override 用在方法上,表示这个方法重写了父类的方法
@Deprecated 表示这个方法已经过期,不建议开发者使用
@SuppressWarnings 忽略警告信息
@SafeVarargs 当使用可变数量的参数的时候,而参数的类型又是泛型T的话,就会出现警告。 这个时候,就使用@SafeVarargs来去掉这个警告
@FunctionalInterface这是Java1.8 新增的注解,用于约定函数式接口。 - 自定义注解
1.通过接口的形式自定义注解
2.处理注解需要在被注解的地方使用反射机制
参考: 自定义注解 - 元注解
元注解 => 用于注解 自定义注解。
@Target:注解能放在什么位置上(类、方法、属性…)
@Retention:表示生命周期(SOURCE、CLASS、RUNTIME)
@Inherited:表示该注解具有继承性
@Documented :用于生成文档
@Repeatable:若无@Repeatable修饰,注解在同一个位置,只能出现一次 - 仿HIBERNATE注解
参考:仿HIBERNATE注解 (尚且不是很明白框架中注解的具体工作原理)
异常处理
- 常见异常处理手段
try catch finally throws
throws与throw这两个关键字接近,不过意义不一样,有如下区别:
1.throws 出现在方法声明上,而throw通常都出现在方法体内。
2.throws 表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某个异常对象。 - 异常分类
Throwable类是Error和Exception的父类
IO
- 文件对象
使用File类(文件和文件夹都是用File代表) => 常用方法,参考:File重用方法 - 输入/输出流
InputStream:可以从中读出字节序列的对象称为输入流
OutputStream:可以向其中写入字节序列的对象称为输出流
注意:io流与java流库没有任何关系 - 字节流
1.InputStream是字节输入流,同时也是抽象类,只提供方法声明,不提供方法的具体实现。FileInputStream 是InputStream子类
2.OutputStream是字节输出流,同时也是抽象类,只提供方法声明,不提供方法的具体实现。FileOutputStream 是OutputStream子类 - 字符流
字节流不方便处理两个字节表示的Unicode => 使用字符流Reader、Writer解决
FileReader 是Reader子类; FileWriter 是Writer的子类 - 关闭流的方式
1.在try中关闭 => 如果抛出异常,则不会执行关闭流,存在资源占用隐患。
2.在finally中关闭 => 严谨但是繁琐
3.try-with-resources => 会自动关闭 - Java中的字符编码
几种编码的对比:
java使用的是unicode
详见(必看):io中文问题 - io缓存流
1.缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中读取。
2.缓存流在写入数据的时候,会先把数据写入到缓存区,直到缓存区达到一定的量,才把这些数据,一起写入到硬盘中去。按照这种操作模式,就不会像字节流,字符流那样每写一个字节都访问硬盘,从而减少了IO操作
3.缓存流必须建立在一个存在的流的基础上
FileReader => BufferedReader
…其他类似
4.若不等缓存满就把数据写入到硬盘,需要用到flush - io数据流
DataInputStream 数据输入流
DataOutputStream 数据输出流
数据流也是必须建立在一个存在的流的基础上;方便直接读写数,而不用经过字符串转换,参考:数据流 - io对象流/序列化
1.被序列化的类需要实现Serializable接口
2.ObjectOutputStream、 ObjectInputStream分别用于序列化/反序列化对象
3.对象流也是必须建立在一个存在的流的基础上
集合框架
- ArrayList常用方法
add 增加
contains 判断是否存在
get 获取指定位置的对象
indexOf 获取对象所处的位置
remove 删除
set 替换
size 获取大小
toArray 转换为数组
addAll 把另一个容器所有对象都加进来
clear 清空
集合内容比较多,需要下来多练习,更多参考:集合框架
JDBC
- 使用JDBC的整个过程
加载mysql驱动 => 建立连接(Connection) => 创建Statement => 执行sql => 关闭连接
可见直接使用 jdbc 非常麻烦,使用mybatis更加方便 - PreparedStatement
和 Statement一样,PreparedStatement也是用来执行sql语句,优点如下:
1.使用参数设置,可读性好,不易犯错 <=> Statement需要字符串拼接
2.PreparedStatement有预编译机制,性能比Statement更快
3.防止SQL注入式攻击,参考:SQL注入攻击 - jdbc事务
在事务中的多个操作,要么都成功,要么都失败
通过 c.setAutoCommit(false);关闭自动提交
使用 c.commit();进行手动提交 - jdbc ORM
ORM:Object Relationship Database Mapping(对象关系数据库映射) =>即一个对象对应关系数据库表中的一条记录 - jdbc DAO
DAO:Data Access Object(数据访问对象)
=> DAO实际上就是把数据库相关的操作都封装在这个类里面,其他地方看不到JDBC的代码,参考:DAO - jdbc 数据库连接池
类似于线程池
a.与传统方式不同,连接池在使用之前,就会创建好一定数量的连接。
b.如果有任何线程需要使用连接,那么就从连接池里面借用,而不是自己重新创建.
c.使用完毕后,又把这个连接归还给连接池供下一次或者其他线程使用。
d.倘若发生多线程并发情况,连接池里的连接被借用光了,那么其他线程就会临时等待,直到有连接被归还回来,再继续使用。
整个过程,这些连接都不会被关闭,而是不断的被循环使用,从而节约了启动和关闭连接的时间。原理如图:
Socket编程
- 网络编程流程
服务端:创建ServerSocket对象 => ss对象accept()方法阻塞线程,收到连接后返回 Socket对象 => 从Socket对象获取io流接收数据 => 关闭资源、连接
客户端:创建 Socket对象自动建立连接 => 从Socket对象获取io流发送数据 => 关闭连接 - 通信双方如何同时收发消息
为双方都各自创建一个发送进程、一个接受进程…
参考:多线程聊天
Servlet
- servlet必知
1.servlet继承自HttpServlet
2.Servlet 本身不能独立运行,需要在一个web应用中运行,而一个web应用是部署在tomcat中的(tomcat是一个servlet/jsp容器,依赖于jre)
3.serlvet不含main方法!!!
4.servlet部署在tomcat中时,是通过xml配置文件指定访问路径与调用的servlet的映射关系的
5.tomcat与servlet之间的交互参考:https://blog.csdn.net/u013956836/article/details/43731663 - servlet获取参数
request.getParameter - servlet返回响应
response.getWriter().println() - service方法
实际上,在执行doGet()或者doPost()之前,都会先执行service()
由service()方法进行判断,到底该调用doGet()还是doPost() - servlet生命周期
1.当需要调用servlet的时候,tomcat发现尚未实例化servlet,会自动对其实例化(servlet是单例,只会实例化一次,注意线程安全,参考:彻头彻尾理解单例模式与多线程
)
2.实例化后会立即执行servlet的init()方法(同样只执行一次)
3.service(…)中编写业务代码,提供doGet()、doPost()服务
4.tomcat关闭或者重启时会调用servlet的destroy()方法
5.当下一次垃圾回收GC来临的时候,就有可能被回收。 - servlet跳转
服务端跳转后浏览器地址不会改变(属同一次请求)
客户端跳转后浏览器地址会改变
浏览器上的地址代表浏览器发起的请求的地址,而不是当前看到的信息的地址!!!(对于ajax请求,由于请求是xhr对象发出,而不是浏览器直接发出,因此浏览器地址栏也不会改变) - servlet上传文件
https://how2j.cn/k/servlet/servlet-upload/587.html
JSP
- jsp必知
1.jsp类似于在html中写java; servlet类似于在java中写html
2.jsp最终都是转换成servlet,最后返回前端html的(使用jsp只是为了程序员方便)
3.jsp与前后端分离的区别=>servlet/jsp返回的是整个页面的html; 而前后端分离仅仅返回数据 - cookie
Cookie是由服务器端创建,但是不会保存在服务器。
创建好之后,发送给浏览器。浏览器保存在用户本地。
下一次访问网站的时候,就会把该Cookie发送给服务器(在http报文的cookie字段)
- session
会话指的是从用户打开浏览器访问一个网站开始,无论在这个网站中访问了多少页面,点击了多少链接,都属于同一个会话。 直到该用户关闭浏览器为止,都属于同一个会话;session对象保存数据的方式,有点像Map的键值对(key-value); cookie与session的关系:
- cookie、session、token的关系
cookie与session的关系见上图
1.cookie:保存在客户端字符信息,首次访问网站时由服务端生成并返回给客户端,浏览器保存cookie到本地(cookie中可以保存sessionID),之后访问浏览器自动在请求头加上cookie
2.session:保存在服务端的与客户端的会话,可以是任何类型的信息。客户端首次访问时由服务端创建并返回sessionID,客户端将sessionID保存在cookie中,之后客户每次请求都会捎上sessionID。服务端据此判断用户是否登录(服务端并非必须创建session,由开发者决定)
3.token:令牌,是用户身份的验证方式.首次登录,服务器生成一个Token并将此Token返回给客户端,之后请求数据捎上token即可验证身份,无需再用户名和密码.
4.session与token的区别:二者都用于身份验证,但是session会保存在服务端且存储的信息可能不止SID,带来内存消耗; 对token而言,服务端根据请求中的用户信息经过加密后返回token,客户端再次请求时服务端会再次对请求进行加密,将用户信息加密后的结果与捎过来的token对比,服务端不需要保存任何信息。
参考:https://blog.csdn.net/mydistance/article/details/84545768 - 使用无cookie的session
如果希望cookie被禁用时,Session状态还是能工作,就应该使用无Cookie的会话。当启用无Cookie的会话时,用户的会话ID 添加到页面的URL中。参考:https://how2j.cn/k/jsp/jsp-session/583.html - jsp作用域、隐式对象、JSTL、EL
MVC
- mvc的含义
模型(M)就是数据,就是dao,bean
视图(V)就是网页, JSP,用来展示模型中的数据
控制器(C )用来把不同的数据,显示在不同的视图上。 在这个例子的,Servlet就是充当控制器的角色,把Hero对象,显示在JSP上=>https://how2j.cn/k/mvc/mvc-tutorials/561.html#nowhere(servlet+jsp就是一种MVC思想,servlet是控制器、jsp是视图) - MVC与MVVM
参考:mvc和mvvm的区别
最后一个VM代表ViewModel,可理解为M和C的中间层,主要负责解析模型数,然后将解析后的数据传递给控制器
MVVM主要用于前端框架,MVC主要用于后端?? - 实际开发中各层之间的关系
- 参考:MVC中model、dao、view、controlller、service之间的关系
model:对数据的封装,与数据库表对应 =>也常命名为entity、domain
dao: 对数据库进行数据持久化操作 =>Mybatis中对应称为mapper
service:是业务代码实现层,供controller调用
----------------------------------------------- => 以上都对应模型
controller:处理请求,调用service =>对应MVC的控制器
view:视图,即页面代码jsp、html等 => 对应MVC的视图
Spring
- IOC
控制反转:简单说就是创建对象由以前的程序员自己new 构造方法来调用,变成了交由Spring创建对象并管理。
- DI
依赖注入:简单地说就是拿到的对象的属性,已经被注入好相关值了(注入什么值在xml文件中配置),直接使用即可。 - spring注解方式的IOC/DI
可以不在xml中配置属性以及对象的注入 => 直接使用注解的方式
@Autowired,当属性是对象是, 在属性前加上@Autowired可以给Bean注入对象
@Component(“name”),在声明Bean类时使用此注解可不用配置xml文件,指明这个类是一个Bean,但是属性的初始化需要放到声明的地方! - AOP
在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能。所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务;所谓的周边功能,比如性能统计,日志,事务管理等等
周边功能在Spring的面向切面编程AOP思想里,即被定义为切面
在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发
然后把切面功能和核心业务功能 “编织” 在一起,这种能够选择性的,低耦合的把切面和核心业务功能结合在一起的编程思想,就叫做切面编程 =>耦合是通过将核心功能的方法传递到辅助功能的方式之中执行!!
参考:https://how2j.cn/k/spring/spring-aop/89.html#step1878 - spring注解方式的AOP
@Component(“name”) 表示这是一个bean,由Spring进行管理
@Aspect 注解表示这是一个切面
@Around(value = “…”)表示要执行的方法!
SpringMVC
- springmvc原理
1.web.xml中配置,使所有的访问都会经过DispatcherServlet
2.springmvc-servlet.xml中配置,使访问路径/index会进入IndexController类
3.在IndexController中指定跳转到页面index.jsp,并传递message数据(ModelAndView)
4.在index.jsp中显示message信息 - springmvc注解方式
1.在控制器类前面加上@Controller 表示该类是一个控制器
2.在方法handleRequest 前面加上 @RequestMapping("/index") 表示路径/index会映射到该方法上
3.在xml中配置使扫描有@Controller注解的类
MyBatis
- mybatis的作用
用了Mybatis之后,只需要自己提供SQL语句,其他的工作,诸如建立连接,Statement, JDBC相关异常处理等等都交给Mybatis去做了,那些重复性的工作Mybatis也给做掉了,我们只需要关注在增删改查等操作层面上,而把技术细节都封装在了我们看不见的地方。 - mybatis的原理
注:也可通过注解,不用在xml中进行那么多配置
SSM
- SSM原理
Redis
- 五种常见数据类型
String(字符串)
List(列表)
Hash(字典)
Set(集合)
Sorted Set(有序集合)
Docker
主要是明白如何使用:Docker
Docker一些概念上的理解:Guide Docker
杂七杂八
- POJO与JavaBean
POJO全称是Plain Ordinary Java Object / Pure Old Java Object,中文可以翻译成:普通Java类,具有一部分getter/setter方法的那种类就可以称作POJO,但是JavaBean则比 POJO复杂很多, Java Bean 是可复用的组件,对 Java Bean 并没有严格的规范,理论上讲,任何一个 Java 类都可以是一个 Bean 。但通常情况下,由于 Java Bean 是被容器所创建(如 Tomcat) 的,所以 Java Bean 应具有一个无参的构造器,另外,通常 Java Bean 还要实现 Serializable 接口用于实现 Bean 的持久性。 Java Bean 是不能被跨进程访问的。JavaBean是一种组件技术,就好像你做了一个扳子,而这个扳子会在很多地方被拿去用,这个扳子也提供多种功能(你可以拿这个扳子扳、锤、撬等等),而这个扳子就是一个组件。一般在web应用程序中建立一个数据库的映射对象时,我们只能称它为POJO。 =>不好理解 - 关于jsp
JSP从来没有传递到前端,每次返回前端的都是jsp转换成servlet后生成的html文件(浏览器看到的带.jsp的路径只是表示请求的地址/接口,而非当前看到的页面地址) - 浏览器上的地址到底代表什么