一、java基础
1.java语言的优势
java是一种跨平台,适合于分布式计算环境的面向对象编程语言。
特性:面向对象、平台无关、简单性、多线程、可靠、安全
1)面向对象:封装、继承、多态
封装:是用一个自主式框架把对象的数据和方法联在一起形成一个整体。
对象是支持封装的手段,是封装的基本单位。
继承:一个对象直接使用另一个对象的属性和方法,
是面向对象编程中的一种代码复用的方式。只支持单继承。
多态:“一个对外接口,多个内在的实现方法” 2)平台无关:java主要靠java虚拟机实现平台无关。
3)简单性:java相对于C++语言比较简单。
4)多线程:java内置多线程控制,简化多线程应用程序的开发。
5)可靠:java是强类型的语言,要求显式的方法声明,
保证了编译器可以发现方法调用错误,保证程序更加可靠;
java不支持指针,杜绝了内存的非法访问;GC防止内存泄漏问题;
- 安全:java通过自己的安全机制防止病毒程序的产生和下载程序对本地系统的
威胁破坏;
2.变量:
1)java中变量就是变化数值的载体
2)注意事项:
1.已经声明的变量不能再次声明
2.为变量赋值必须匹配类型
3.必须先声明再初始化才能使用
3)变量的命名:
规则:
- 允许字母、数字、_、$做变量名的组成部分,数量不限,
数字不允许开头;
2.不能包含空格
3.大小写敏感
4.关键字不能做变量名
规范:
1.使用英文单词命名
2.见名知意
3.多个单词组成时:驼峰命名法
3.数据类型:
基本数据类型、引用数据类型
基本数据类型:
byte short int long float double boolean char
字节 1 2 4 8 4 8 1 2
取值范围 -2^7~2^7-1 -2^15~2^15-1 -2^31~2^31-1 -2^63~2^63-1 true false 0~65535
直接量:直接编写在代码中的数字,整型是int,小数是double
4.运算符和表达式:
算数运算符:+ - * / %
关系运算符:> < >= <= == !=
逻辑运算符:&& || !短路特性
赋值运算符:=
复合赋值运算符:+= -= *= /= %=(内置强制类型转换)
字符串连接符:+
自增自减运算符:++ --
条件运算符(三目运算符):boolean?true:false
5.程序结构:
1)顺序结构:编写的每行代码一定会执行一次
2)分支结构:编写的代码可能会执行一次
单分支:if
双分支:if-else
多分支:if-else if 特别适合于判断一个值在一个范围的情况
switch case default 使用灵活,结构简单,运行效率高,适合于等值判断
3)循环结构:编写的代码可能会执行多次
要素:循环变量、循环条件、循环操作、变量更新
while
do while
for
循环次数固定首选for循环
循环次数不确定:一定会至少执行一次的do while
有可能一次都不执行的while
循环中的流控语句:break,continue
循环嵌套:break或continue作用是内层循环,可以使用标记跳出指定循环
6.数组:是一组相同数据类型的数据的集合
数组的构成:数组名、数组元素、数组长度、数组下标
特征:
1)数组的长度是固定的
2)数组中只能保存相同数据类型的数据
3)数组元素是有默认值的
数组的复制:
System.arraycopy();
Arrays.copyOf();
数组的排序:
Arrays.sort();//结果为升序
7.方法:程序中,处理一个功能或业务的代码块
1)为什么要用方法:
1.将处理不同业务的代码从程序入口中分离出来,降低代码复杂度
2.每个方法专心的编写自己的业务,不和其他业务干扰
3.各种方法在main方法中调用,方便团队开发
4.方法可以编写一次,调用多次
2)方法的定义:
1.无参无返回值
2.无参有返回值
3.有参无返回值
4.有参有返回值
二、面向对象
减少代码冗余,提高程序的可维护性和可扩展性
1.重载:方法名相同,参数列表不同(可以发生在同一类,也可以发生在父子类)
重写:方法名,参数列表相同,返回值类型如果是void或基本数据类型,
则返回值类型也要相同,如果是引用类型,可以是父类返回值类型的子类。
访问权限不能比父类更严格。
2.构造方法:
构造方法主要作用是给成员变量赋值
1)构造方法是创建对象时会执行的方法,名称与类名相同,不声明返回值类型
2)如果某个类没有显式的定义构造方法,则编译器会自动添加一个公有的、无参
数的构造方法,如果已经显式的定义构造方法,则编译器不会干预。
3)构造方法是可以重载的,某个类中可以同时存在多个构造方法
构造方法的应用场景:
1)创建类的对象,快速的设置相关属性的值;
2)限制对象的创建过程,甚至不允许直接创建对象;
3)通过在构造方法中添加参数,强制要求得到某些数据;
3.this关键字
1)调用当前对象的属性
2)调用当前对象的方源
3)调用当前类的构造,必须编写在当前类构造方法中的第一行
super关键字
构造方法的第一行如果不写this()或super(),默认为super();
final关键字
修饰类:不允许被继承
修饰方法:不能被重写
修饰成员变量:不允许被修改,在被对象实例化之前必须被赋值(声明的同时赋值
,构造方法中赋值);
修饰局部变量:只能被赋值一次(修饰形参);
修饰引用数据类型:属性值可以变,引用不能变化;
static关键字
静态变量保存在方法区,每个类只能存一份,使用类名调用
静态方法没有也不能使用this,不能重写
静态块:无论实例化多少对象,只运行一次,最先运行(JVM加载这个类时运行)
常量
常量被使用时,在编译时就确定值,运行时直接使用,提高运行效率
命名规范:所有字母均大写,使用_来分割单词
一般声明的同时赋值,也可以在静态块中赋值,但不推荐,因为效率低。
4.抽象方法
特征:1)抽象方法不能编写方法体
2)抽象方法必须在子类中被重写,除非子类也是抽象类
abstract和final不能同时修饰类或方法
5.内部类:在一个类中,又编写了另一个类
成员内部类可以使用4种访问修饰符
成员内部类中的方法可以访问外部类中的私有成员
外部类可以中方法中实例化内部类对象,并访问内部类的私有成员
所有内部类在编译之后,都会产生自己独立的class文件
匿名内部类:
1.通常编写在方法中
2.可以使用外部类中的私有成员
3.方法中不能修改局部变量的值,局部变量只能被赋值一次,jdk1.6之前
所有局部变量都必须使用final修饰
6.接口
使用接口能实现java中的多继承
接口中的所有属性都是:公有静态常量
方法是:公有抽象方法(jdk1.8之后可以有普通方法)
接口中不允许有构造方法,不能实例化
7.垃圾回收机制的优点和不足:
优点:java程序员,不需要考虑垃圾回收的问题
缺点:
1.垃圾回收管理机制本身是占用内存的
2.垃圾回收的时机,并不是立即的
3.垃圾回收的机制,只能回收java程序中产生的垃圾,在其他媒介中产生
的垃圾要手动回收
判定规则:内存中保存对象被引用的个数为0
final
修饰类:不允许被继承
修饰方法:不能被重写
修饰成员变量:不允许被修改,在被对象实例化之前必须被赋值(声明的同时赋值
,构造方法中赋值);
修饰局部变量:只能被赋值一次(修饰形参);
修饰引用数据类型:属性值可以变,引用不能变化;
finally
java的一种异常处理机制,finally结构中的代码总会执行
finalize
是Object类中编写的一个方法,被垃圾回收管理机制在回收这个对象前调用
三、JavaSE
1.String
1.支持正则表达式
1)boolean matches(String regex)
使用给定的正则表达式匹配当前字符串是否符合格式要求,符合则返回true
2)String replaceAll(String regex,String str)
将当前字符串中满足正则表达式的部分替换为给定内容
3)String split(String regex)
将当前字符串中挖宝按照满足正则表达式的部分拆分,然后将拆分后的字符串
以数组形式返回
2.char charAt(int index)
获取当前字符串中指定位置对应的字符
3.int indexOf(String str)
查找给定字符串在当前字符串中的位置,若当前字符串中不包含给定内容则返
回值为-1
4.int length()
获取当前字符串的长度
5.String substring(int start,int end)
截取当前字符串中指定范围的字符串
6.boolean startsWith(String str)
boolean endsWith(String str)
判断字符串是否以给定的字符串开始或结尾的
7.String valueOf(XXX xxx)
String静态方法,作用是将给定的内容转换为字符串
8.String trim()
去除当前字符串两侧的空白字符
9.String toUpperCase()
String toLowerCase()
将当前字符串中的英文部分转换为全大写或全小写
10.StringBuilder
String str="";
StringBuilder builder=new StringBuilder(str);
builder.append("需要填加的字符");//增
builder.delete(x,x);//删
builder.replace(x,x,"修改后的字符");//改
builder.insert(x,"需要填加的字符");//插
System.out.println(builder.toString());
2.Integer(包装类)
1.int d=0;
Integer in=Integer.valueOf(d);
int i=in.intValue();
2.String str="123";
int i=Integer.parseInt(str);
3.int imax=Integer.MAX_VALUE;
3.file
1.File file=new File(目录);//获取名为file的文件
boolean file.exists();//判断文件是否已存在
file.createNewFile();创建file文件
file.getName();//获取文件名
file.length();//获取长度
file.getAbsolutePath();//获取绝对路径
boolean file.canRead();//是否可读
boolean file.canWrite();//是否可写
boolean file.isHidden();//是否为隐藏文件
boolean file.isFile();//是否为文件
boolean file.isDirectory();//是否为目录
File[] file.listFiles();//获取当前目录中所有子项
2.过滤器
File file=new File(".");
FileFilter filter=new FileFilter(){
public boolean accept(File pathname){
String name=pathname.getName();
return name.startsWith(".");
}
};
File[] subs=file.listFile(filter);
3.删除文件、目录
File file=new File(./test.txt);
file.delete();
4.创建目录
mkdir() mkdirs()
4.raf(基于指针)
1.RandomAccessFile raf=new RandomAccessFile("文件路径","rw");
raf.write(1);//向文件写入1字节
raf.close();
RandomAccessFile raf=new RandomAccessFile("文件路径","r");
raf.read();//读取1字节文件
raf.writeInt();//写入4字节 -- raf.readInt();
raf.writeLong(); -- raf.readLong();
raf.writeDouble(); -- raf.readDouble();
raf.seek(x);//将指针移动到x下标位置
raf.getFilePointer();//返回指针下标位置
2.写入字符串
RandomAccessFile raf=new RandomAccessFile("文件路径","rw");
String line="";
byte[] data=line.getBytes("UTF-8");
raf.write(data); || raf.write(data,x,x)//每次写入固定长度的字节
3.读取字符串
byte[] data=new byte[(int)raf.length()]
raf.read(data);
String str=new String(data,"UTF-8");||(data,x,x,"UTF-8")
5.io
1.FIS--FOS 文件流
2.ISR--OSW 转换流:负责衔接字符高级流与字节流
3.OIS--OOS 对象输入输出流
4.BW--BR 缓冲流
5.PW 缓冲流(自动行刷新)
6.Thread(线程)
1.Thread t=new Thread(){
public void run(){
}
};
t.start();
2.Runnable r=new Runnable(){
public void run(){
}
};
Thread t=new Thread(r);
t.start();
3.currentThread(); 获取线程
4.getName(); 获取名字
5.long getId(); 获取唯一标识
6.int getPriority(); 获取优先级 setPriority();设置优先级
7.boolean isAlive(); 线程活着
8.boolean isDaemon(); 线程死了
9.boolean isInterrupted(); 线程中断
10.setDaemon(true); 设置守护线程要在线程启动前进行
11.join(); sleep();阻塞 interrupt();打断阻塞
12.synchronized 同步块
synchronized(类名.class) 静态方法
它们最大本质的区别是:
sleep()不释放同步锁,wait()释放同步锁.
还有用法的上的不同是:sleep(milliseconds)可以用时间指定来使他自动醒
过来,如果时间不到你只能调用interrupt()来强行打断;wait()可以用notify()
直接唤起.
13.线程理论:
1.进程:操作系统进行资源调度和分配的基本单位(例如:浏览器,APP,JVM);
2.线程:进程中的最小执行单位;
3.并发:多线程抢占CPU,可能不同时执行,侧重于多个任务交替执行;
4.并行:线程可以不共享CPU,可每个线程一个CPU同时执行多个任务;
5.线程的状态:新建状态,就绪状态,运行状态,阻塞状态,死亡状态;
static String content;
public static void main(String[] args)throw new Exception{
Thread t = new Thread(){
public void run(){//运行状态
content = "helloworld";
};//run方法执行结束线程处于死亡状态
};//新建状态
t.start();//就绪状态(可运行状态)
//Thread.sleep(1000);//主线阻塞
//t.join();//让t线程执行结束,主线程阻塞
while(content == null){
Thread.yield();//让当前线程放弃CPU,处于就绪状态
}
System.out.println(content.toUpperCase());
}
- 多个线程并发执行时,仍旧能够保证数据的正确性,这种现象称之为线程 安全;
- 多个线程并发执行时,不能够保证数据的正确性,这种现象称之为线程不安全;
8.synchronized排他锁(独占锁,非公平锁);
9.实例方法默认锁是this,静态方法默认锁是类名.class;
10.volatile:禁止指令重排序;
11.导致线程不安全的因素有哪些?
1)多个线程并发执行;
2)多个线程并发执行时存在共享数据集(临界资源);
3)多个线程在共享数据集上的操作不是原子操作(不可拆分);
12.如何保证并发线程的安全性?
1)对共享进行限制访问(例如加锁:syncronized,Lock):多线程在同步
方法或同步代码块上排队;
- CAS(比较和交换)实现非阻塞同步(基于CPU硬件技术支持),
CAS算法支持无锁状态下的并发更新,但可能会出现ABA问题,长时间自旋问题;
- 取消共享,每个线程一个对象实例(例如threadlocal),connection、
SimpleDateFormate、SqlSession不允许线程共享,需要使用threadlocal;
class Counter02{
private volatile int count;
//公平锁,独占锁,排他锁
private Lock lock = new ReentrantLock(true);
public void count(){
lock.lock();//加锁
try{
count++;
}finally{
lock.unlock();//解锁
}
}
}
class Counter03{
//底层使用CAS算法(基于CPU硬件实现,内存地址、期望数据值、需要更新的值)
private AtomicInteger at = new AtomicInteger();
public void count(){
at.incrementAndGet();
}
}
class DateUtils{
private static ThreadLocal<SimpleDateFormate> td = new ThreadLocal<>();
public static String format(Date date){
//从当前线程获取SimpleDateFormat对象
SimpleDateFormate sdf = td.get();
if (sdf != null){
return sdf.format(date);
}
//当前线程没有则创建SimpleDateFormat并且存入当前线程
sdf = new SimpleDateFormate("yyyy/MM/dd");
td.set(sdf);//ThreadLocal关联了一个线程,线程中有一个Map,key为td(ThreadLocal)
return sdf.format(date);
}
}
13.Synchronized:基于Monitor对象实现同步;
14.Synchronized锁优化:锁的级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态;锁可以升级不可以降级;
15.volatile:一般用于修饰属性变量
1)多核或多cpu场景下保证变量的可见性。
2)禁止指令的重排序操作
3)不保证原子性
16.在JMM中如果一个操作A Happened——before 另一个操作B,那么A操作的结果对B操作的结果是可见的,那么我们称这种方式为happened——before原则 ;
17.JMM中基于happened——before规则,判定数据是否存在竞争,线程是否安全,以及多线程环境下变量值是否是可见的;
18.JAVA中为了保证多线程并发访问的安全性,提供了基于锁的应用,大体可归纳为两大类,即悲观锁和乐观锁;
悲观锁:假定会发生并发冲突,屏蔽一切可违反数据完整性的操作,同一时刻只能有一个线程执行写操作。
syncronized,lock,ReadWriteLock
适合写操作比较多的场景,写可以保证写操作时数据正确;
乐观锁:假设不会发生冲突,只在提交操作时检查是否违反数据完整性,多个线程可以并发执行写操作,但只能有一个线程写操作成功。
CAS算法
适合读操作比较多的场景,不加锁的特点能够使其读操作的性能大幅提升;
19.减少多线程上下文切换的方案:
1)无锁并发编程:锁的竞争会带来线程上下文的切换;
2)CAS算法:CAS算法在数据更新方面,可以达到锁的效果;
3)使用最少线程:避免不必要的线程等待;
4)使用协程:单线程完成多任务的调试和切换,避免多线程;
20.如何避免死锁?
1)避免一个线程中同时获取多个锁;
2)避免一个线程在一个锁中获取其他的锁资源;
3)考虑使用定时锁来替换内部锁机制,如lock.tryLock(timeout);
7.collection(集合)
1.collection:
Collection<> c=new ArrayList<>();
c.add(); 填加元素 返回值boolean类型
c.size(); 返回集合元素个数
boolean c.isEmpty(); 是否为空集
c.clear 清空集合
c.addAll(集合);
boolean containsAll(集合) 判断是否全包含集合 contains();
removeAll(集合) 删除共有元素 remove();
遍历集合:
1)for(元素类型:集合){
}
2)迭代器
Iterator<> it=c.iterator();
while(it.hasNext()){
String str=it.next();
}
2.List<>list=new ArrayList<>();
E get(int index); 获取给定下标处对应的元素
E set(int index,E e); 将给定元素设置到指定位置上,返回值为原位置对应的元素
list.add(int index,"");指定位置插入元素
list.subList(); 子集
Collections.sort(list); 排序
Collections.sort(list,new comparator<>(){
});
3.数组转集合
List<>list=Arrays.asList(数组);
List<>list2=new ArrayList<>(list);
4.集合转数组
String[] arr=list.toArray(new String[list.size()]);
5.Map<key,value>map=new HashMap<>();
map.put();//成对填加元素
map.get();//查询
map.containsKey(key);// 检查map中是否包含指定key
6.Set<Entry<key,value>> set = map.entrySet();
getKey();
getValue();
7.集合理论:
1.Collection:集合的父接口 Collections:是针对集合的帮助类,提供了一系列
静态方法实现集合的排序等。
1.List:
有序,可重复
get,set,subList,toArray,asList
- ArrayList:采用数组方式存储数据,允许直接序号索引元素,索引
数据快,插入数据慢,数组长度增长率为目前长度的50%,线程
不安全
- Vector:数组长度增长率为目前长度的100%,线程安全,性能比
ArrayList差
3)LinkedList:采用双向链表实现存储,插入数据快,索引数据慢
2.Set:
无序,不能重复
2)HashSet:(无序)是哈希表实现的,允许存入一个null值,要求存入的对象必须实现hashCode()
底层是HashMap
3)TreeSet:(有序)是二叉树实现的,里面的数据是自动排好顺序的,不允许存入null值
2.Map:
键值对、键唯一、值不唯一
1.HashMap:是最常用的Map,根据键的HashCode值存储数据,线程不安全
LinkedHashMap:保存了记录的插入顺序
2.Hashtable:线程安全,效率低,不允许键或者值为null
3.TreeMap:能够把保存的记录根据键排序,默认是升序,不允许key为空,线程不安全
3.遍历:
List:ListIterator,for,foreach
Set:Iterator,foreach
Map:
keySet(),entrySet(推荐)
四、框架
1.springboot配置拦截器
1)创建拦截器类实现HandlerInterceptor接口,重写prehandle方法
2)创建配置类实现WebMvcConfigurer接口,重写addInteceptors方法
2.购物车逻辑
1)根据传递过来的商品id和用户id查询数据库购物车表中的商品信息
2)结果为null:将数据封装到购物车实体类,执行插入操作
3)不为null:获取结果中的商品数量、购物车id,将数量重新计算执行修改操作
1.Git
工作区:保存项目的元数据和对象数据库的地方
暂存区:保存下次将提交的文件列表信息
版本库:本地版本库
远程仓库:可以看做是github,它是一个远程仓库
命令:
git clone <url> 克隆远程版本库
git init 初始化本地版本库
git add . 跟踪所有改动过的文件
git remote add <remote> <url> 添加远程版本库
git commit -m "commit message" 提交所有更新过的文件
git push <remote> <branch> 上传代码及快速合并
git pull <remote> <branch> 下载代码及快速合并
git log 查看提交历史
git config --global user.name "name"
git config --global user.email "email"配置身份信息
git reset --hard "UUID" 回退版本
git push -f -u origin master 强制提交到远程仓库
2.Servlet:
Servlet是用来扩展web服务器功能的组件
Servlet是如何运行的:
1.浏览器依据ip、port建立连接
2.浏览器将相关数据打包,发送请求
3.容器解析请求数据包,并且将解析到的数据封装到request对象,
同时创建一个response对象。
4.容器创建servlet对象,然后调用该对象的service方法。
(容器会将request和response作为参数传进来,可以通过
request获取请求参数,也可以将处理结果放到response
对象中)
5.容器读取response对象中的处理结果,然后将处理结果打包发送
给浏览器。
6.浏览器解析响应数据包,生成响应的页面
Servlet的生命周期
实例化,初始化,就绪,销毁
Servlet中,可以保存数据三个不同的作用域是:request,session,application
HTTP协议
网络应用层协议,规定了浏览器与服务器之前是如何通信以及相应数据包的格式
如何通信:建立连接,发送请求,发送响应,关闭连接
重定向与转发的区别:
1)共享request和response,转发可以,重定向不可以
2)转发是一次请求组件间的数据,重定向是两次请求不共享组件间的数据
3)重定向的地址栏的地址改变,转发不会
4)重定向的新地址是任意的,转发的新地址必须是同一个应用内的地址
JSP:是java服务器端动态页面技术
向JSP中添加java代码的三种方式
java代码片段、jsp表达式、jsp声明<%! %>
JSP隐含对象:out,request,response,session,application,pageContext
page,config,exception
隐含对象的作用:可以简化http请求响应信息的时间
JSP中常用的指令:page,include,taglib
状态管理:cookie session
3.Class.forName()和Class.loadClass()的区别
forName("")得到的class是已经初始化完成的
loadClass("")得到的class是还没有连接的
4.CAP理论
一致性指更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致,所以,一致性,说的就是数据一致性。
可用性:每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据
分区容错性: 分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。
5.BASE理论是对CAP理论的延伸,BASE是指基本可用、软状态、最终一致性。
基本可用是指分布式系统在出现故障的时候,允许损失部分可用性。
响应时间上的损失:正常情况下搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出现故障(比如系统部分机房发生断电或断网故障),
查询结果的响应时间增加到了1~2秒。
功能上的损失:购物网站在购物高峰(如双十一)时,为了保护系统的稳定性,部分消费者可能会被引导到一个降级页面。
软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据会有多个副本,允许不同副本同步的延时就是软状态的体现。
最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。
6.feign是声明式的web service客户端
7.单点登录
ticket:混淆性(UUID)、唯一性(用户名)、动态性(系统时间)
java对象转换成json串:ObjectMapper