你要的Java基础笔记在这里
java基础
目录
StringBuffer and StringBulider
类的关系之继承
方法重写override 方法重载overload
- 类 产生两个继承关系的类 一个类中的一组方法
子类重写父类的方法
- 权限 子类可以大于等于父类 没有要求
- 特征 finale static abstract 没有要求
父类方法是final子类不能重写
父类方法是static子类不能重写
类和类的关系
继承 is a
聚合关系 A has a B A里面有B public Computer computer;
依赖关系 A need a B A需要B 直接传参数在方法里面去和new都可以
修饰符
本包指的是同一个包 不算同一个包里面的包
Public 只要不出工程哪里都可以访问
Protected 保护的 本类 本包 在子类的范围类(this.)只有在子类的范围内部通过你子类自己才可以访问和创建对象都可以访问
默认 默认的 本类 本包
final something |
Private 私有的 本类 \
Final 最终不可以变的
修饰变量 存在栈内存里面
修饰属性 存在堆内存里面
修饰方法
修饰类本身 一般用法 public final class Test 也可以final放在最前面
修饰变量:如果在定义时没有给变量付初始值就可以给变量一次赋值的机会(因为变量在栈内存中没有默认值如果不给机会就不能用了)
如果被final修饰的是基本类型的话则他的值不能变了
如果是引用类型那么他的引用不能变值可以变化
修饰属性:全局变量如果定义为final那么必须赋初始值不然报错
修饰方法:方法是最终的方法 不可被更改
子类继承父类的方法 将子类的方法重写(覆盖)
Final修饰的方法 要求不可以被子类重写(覆盖)
修饰类本身:类是最终的 不可被更改
(太监类 无后)此类不可以被其他子类继承
通常是一些定义好的工具类
包装类 String Math Scanner
Static静态修饰符
Static可以修饰: 属性 方法 块 修饰类(内部类)
特点:
- 静态元素在类加载的时候就初始化了,创建的非常的早,此时没有创建对象
- 静态元素存储在静态元素区中,每个类都有自己的区域,与别的类不冲突
- 静态元素只加载一次(只有一份)全部类对象及类本身共享
- 由于静态元素区加载的时候,有可能没有创建对象,可以通过类名直接访问一般不建议用对象调用
- 可以理解为静态元素不属于任何一个对象,属于类的
- 静态元素去GC无法管理 可以简单粗暴地认为常驻内存
- 非静态成员中(堆内存 对象里)可以访问静态成员变量(静态区)
- 静态成员可以访问静态成员(都存在静态存储区)
- 静态成员不可以访问非静态成员(静态成员属于类加载类是静态成员就已经出来了,比非静态成员先出来)
- 静态元素中不可以出现this和super关键字(静态元素属于类)
设计模式
不是知识点
是一种设计经验的总结
设计模式是用来解决某种场景下的某一类问题à通过的解决方案
有了设计模式之后 可以让代码更容易被理解 确保了复用性 可靠性 可扩展性
设计者模型分为三种
创建型模式(5)种 用于解决创建对象的过程
单例模式 工厂方法模式 抽象工厂模式 建造者模式 原型模式
结构型模式(7)种 把类和对象通过某种形式结合在一起构成某种复杂或合理的结构
适配器模式 装饰者模式 代理模式 外观模式 桥接模式 组合模式 组合模式 享元模式
行为型模式(11)种 用来解决类或者对象之间的交互 更合理的优化类和对象之间的关系
观察则模式 策略模式 模板模式 责任链模式 解析器模式 迭代子模式 命令模式 状态模式 备忘录模式 访问者模式 中介者模式
单列模式(懒汉式,饿汉式)
方法重写 方法重载
类:产生两个继承关系的类 一个类中的一组方法
子类重写父类的方法
权限:子类可以大于等于父类 没有要求
特征:final static abstract 没有要求
父类方法是final子类不能重写
父类方法是static子类不存在
父类方法是abstract子类必须重写(子类是抽象类可以不用重写)
返回值:子类可以小于等于父类(一般是指的继承返回值) 没有要求
名字:子类与父类一致 与其他重写方法一致
参数:子类与父类一致 与其他方法参数必须不一致
异常:运行时 编译时 没有要求
如果父类抛出编译时异常子类可以不予以理会
如果父类抛出运行时异常,子类抛出异常数小于等于父类
子类抛出的异常类型小于等于父类
方法体:子类的方法内容与父类不一致 每个重载方法执行过程不一致
抽象类与接口
修饰方法
abstract
修饰类
抽象类中不是必须要有抽象方法
抽象方法必须放在抽象类或者接口中
抽象方法不可以创建构造方法创建对象来调用
只能创建子类的构造方法来调用
直接单继承指的是指直接继承没有任何的东西(可以加东西)
抽象类 可以直接单继承 抽象类
抽象类 可以直接单继承 具体类(通常不会这么用没意义)
具体类 不可以直接单继承 抽象类(将父类的方法具体化 或者将子类也变为抽象类)
抽象类中可以全部是具体方法 没有抽象方法
抽象方法中可以全部是抽象方法 没有具体方法 抽象到极致了 --> 接口
接口
Public interface 名字{} 接口
属性 必须是 public static final String name="朱沛萌";
方法 必须是含有共有的抽象的方法(jdk 1.8之后可以是default修饰)
块 没有(块本身就是具体的)
构造方法 没有
如何使用创建对象
不能创建对象
只能通过子类多实现(implements)来做事
Public class A implements B,C,D{}
与别的类结构关系
接口类不能继承别的类 最抽象
抽象类 可以直接多实现 接口
具体类 不可以直接多实现 接口(必须将接口中的抽象方法具体化 自己变成抽象类)
接口 多继承 接口 可以直接多实现
匿名内部类
成员内部类:
局部内部类:只能用abstract和final来修饰可以重名访问访问局部变量的时候必须是加了final来修饰的
匿名内部类:成员匿名内部类和局部匿名内部类
静态内部类:
枚举(类)
一个类中的对象 认为个数是优先固定的 可以将每一个对象一一列举出来
包装类
包装类全部放在java.lang(相当于电脑的桌面不需要import导包直接使用)包下
八个包装类有六个是与数字相关的 有两个没有 都默认继承Number
八个包装类都实现了Serializable Comparable
每一个类中的构造方法
八个包装类里面都有自己类对应类型的构造方法
八个里面还有七个带有方构造法重载除了Character都带有String类型的
Integer i1=10;
Integer i2=10;
Integer i3=new Integer(10);
Integer i4= new Integer(10);
System.out.println(i1==i2); true 数字范围-127~128超过之后就就在堆内存里面new
System.out.println(i1==i3); false
System.out.println(i3==i4); false
System.out.println(i1.equals(i2)); true
System.out.println(i1.equals(i3)); true
System.out.println(i3.equals(i4)); true
Math Random类
数学类 Math在java lang包里面 Random类在java.util里面(要导包)
Math构造方法是私有的 我们不能直接创建对象调用
由于Math中提供的方法及属性都是static 不需要创建对象
常用方法
abs()绝对值 ceil()向上取整 rint()找的是最近的整数如果是一半则返回偶数 floor()向下取整 round()四舍五入 pow()取a的b次方 sqrt()开算术平方根
UUID在java.lang包里面
Date类
在import java.util.Date;里面
常用方法before() after() setTime() getTime()(long类型的) compareTo()(-1 1)
处理一个时间的格式
DateFormat 在java.text此时类是抽象类不能创建对象子类来创建SimpleDateFormat
DateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time1 = df.format(date2);
System.out.println(time1);
Calendar类
在java.util需要导包
有构造方法但是是protected自己访问不到通常会调用(静态)getInstance();
常用方法after() befor() getTime(Date) setTinme(Date)
TimeZone在java.util包里面可以通过calendar.TimeZone()得
或者TimeZone.getDefault()获得
常用方法getId()和getDisplayName()
字符串相关
String类在java.lang包不用导包实现了三个接口Serializable CharSequence Comparable<>
默认继承object类
==比较基本类型的话比的是值 引用类型比的是地址
equals在object类中是==要想改变的话就得重写equals方法比如String Integer
System在java.lang包里面
char [] a={‘a’,’b’,’c’,’d’};
String s1 = new String(a);
String的不可变性:String类中包含一个数组private final char []value;
final最终不可变的 地址不让改变本身长度也变不了
private修饰的只能在当前类中访问 数组的内容不让改变
主要体现在两个地方 长度内容
长度 因为数组本身的长度就不可以改变然后还加上了final修饰地址也不可以改变
内容 因为它是private修饰的只能在本类访问不能在外部访问
对象存储
“abc” 在字符串常量
new String(“abc”) 在常量池
String str = "a"+"b"+"c"+"d"字符串拼接中产生了7个对象
value str = “a”+”b”+”c”+”d”;
value[] 数组一 a “a”
value[] 数组二 b “b”
value[] 数组三 {a,b} “ab”
value[] 数组四 c “c”
value[] 数组五 {a,b,c} “abc”
value[] 数组六 d “d”
value[] 数组七 {a,b,c,d} “abcd”
常用的方法
boolean = equals(Object obj)继承自object重写了比较两个字符串是否相等
int = hashCode继承自object重写了将当前字符串的每个char元素拆开乘以31求和
int = compareTo(String str)实现Comparable接口 实现了按照字典(Unicode)索引比较
char = charAt(index);”ask” 0àa
返回对应的index的那个值char类型的
int = codePointAt(index);”jafjf” 1à97
返回对应的index所在位置的code值
int = length()这是方法
返回字符串的长度
String = concat(String)
将给定的字符串拼接在后面
boolean = contains(CharSequence s)
判断给定字符是不是在字符串中
starsWith(String prefix)和endsWith(String suffix)
判断此字符串是否以xx开头结尾
byte[] =getBytes(); -->getByte(String charsetName)
char[] =toCharArray();
int index = indexOf(String/int,);
当前元素出现的第一次索引位置如果不在就返回-1
lastindexOf()与之相反
boolean = isEmpty();
判断字符串是否为空串 ””
replace();
replaceAll();
replaceFirst();
将给定的字符串替换为另外的字符串
split(String regex,int limit)按照给定的格式将字符串拆分后面是拆成几段
String = substring(int begin,int end)截取给定范围类的字符串
toUpperCase() toLowerCase()
将给定的字符串进行大小写转换左开右闭
String = trim()只能去掉字符串前后多余的空格
第一梯队(重写)
equals compareTo hasCode toString
第二梯队(常用)
charAt() codePointAt() indexOf() lastIndexOf() substring() replace() split() length() contains() concat() trim() getBytes() toCharArray() match()
第三梯队(一般)
toUpperCase() toLowerCase() starsWith() endsWith() isEmpty()
boolean = matches(String regex)正则表达式判断 regex正则表达式
StringBuffer and StringBulider
所属java.lang包
默认继承object实现接口Serializable CharSequence Appendable
StringBuffer和StringBulider没有comparaTo方法
StringBuffer和StringBulider含有一个String没有的方法append();拼接
特性
可变字符串 char [] value可以动态扩容
对象的构建
无参构造方发
有参构造方法
StringBuffer sb = new StringBuffer(); 默认是16长度的char数组
StringBuffer sb = new StringBuffer(int length); 可以自定义长度
StringBuffer sb = new StringBuffer("String"); 默认是16+字符串长度
StringBuffer和StringBulider中常用方法
最主要方法append();频繁的拼接字符串使用
ensureCapacity()确保容量够用
capacity()数组的真实长度
length()数组的真实长度
char = charAt(int index); 取给定位置的字符为char类型的
int = codePointAt(int index); 取给定位置的字符的code码
String = substring(int start, int end); 截取给定位置的字符串必须接String(可以不要后面的参数)
StringBuffer() = delete(int start, int end);删除给定位置的值用他自己来接也可以不接他
StringBuffer() = deleteCharAt(int index);给定的位置的字符删了
int = indexOf(String str, int fromindex);寻找某个字符串出现的位置(从前往后寻找)
int = lastIndexOf(String str, int fromindex);寻找某个字符串出现的位置(从后往前寻找)
insert(int index ,value);
replace(int start, int end, String str)替换给定位置的字符串
setCharAt(int index, char value);
将给定位置的字符修改为指定的字符
toString()就是将StringBuffer或者StringBuilder()转换为String类型
trimSize();去掉数组中多余的元素
知识总结
一般是用于频繁的追加字符串append();
常用方法
与String类不同的方法
append() insert() delete() deleteChar() reverse()
与String相同的方法
charAt(); codePointAt(); indexOf(); lastindexOf(); replace(); string();字相同用法不一定一致
StringBuffer和StringBuilder的区别
StringBuffer是jdk1.1 StringBuilder是jdk1.5
早期版本 线程同步 安全性较高 执行效率相对较低
晚期版本 线程非同步 安全性较低 执行效率相对较高
Regular Expression正则表达式
regex带有规律的表达式匹配字符串格式
下面都是描写一个字符的
[abc] 必须是abc其中一个
[a[^bc]] 第一个必须是a后两个不能是bc中一个
[a-zA-Z] 必须是这两个中的一个
[a-z&&[^bc]] 必须是a-z中一个但是不能是bc
. 表示任意一个字符
\d 表示digital数字[0-9]
\D 表示非[^0-9]的数字
\s 表示space留白 如 空白 换行 回车
\S 表示非留白
\w 表示[0-9A-Za-z]中任意一个字符
\W 表示非[^0-9A-Za-z]中的任意一个字符
下面都是描写字符出现的次数的
?出现0-1次
*出现0-n次
+出现1-n次
{n}出现n次
{n,}至少出现n次
{m,n}出现m到n次
//先利用Pattern类创建一个模式 可以理解为正则表达式对象
Pattern pattern = Pattern.compile("\\d{6}");
//创建一个字符串
String value = "134656ahjf123458fhdj654123";
//利用pattern模式创建一个匹配器
Matcher matcher = pattern.matcher(value);
//用匹配器创建出来的对象调用find方法
while(matcher.find()){
//一组一组的输出
System.out.println(matcher.group());
}
需要导包java.util.regex.Matcher; java.util.regex.Pattern;
集合都在java.util包里面
Collection(存储的都是value) Map(以key-value形式存在)
list(有序可以重复) Queue Set(无序不重复) key是无序无重复 value是无序可重复
序:指的是拿进去是第几个然后取出来就是第几个
重复:指的是有重复就不存了两个对象元素对象一致
ArrayList Vector 区别StringBuffer和StringBuilder的区别
List集合
ArrayList Vector LinkList
ArrayList
底层就是一个数组 适合便利和轮询 不适合插入删除
无参构造方法 带默认空间的构造方法 带collection参数的构造方法(可以传入其他几类)
常用的方法 小容器
add(E e) add(int index ,E e)
addAll(Collection c)并集
add(int index,Collection c)
clear()清除集合里面的所有元素
contains(Object);寻找某个元素是否在集合中
int = indexOf(Object) lastIndexOf()
isEmp() Iterator = list.iterator()//迭代器
remove(int index) remove(Object)
removeAll()差集
retainAll()交集
set(int index,E value)
List<E> = subList(int start, int end);
toArray(); toArray(T[]);
trimSize()真实元素那么长
由于ArrayList底层是Object[]数组什么类型都可以存进去
取出来的时候是多态效果所以去出来的时候需要造型显得非常的麻烦
jdk1.5 之后出现了泛型概念
泛型
用来判定数据类型的 定义的时候用某种符号来代替某种类型
在使用的时候应该把那个符号换成具体类型
泛型可以用在那里
泛型类可以放在类的后面集合就是这样的
泛型接口
与集合类用法差不多一致子类用的时候必须写为具体的型
public interface Test<T>{
public T value;
}
public class Son<T> implements Test<T>{}
泛型方法
调用方法时在给他定型 与类无关 可以在没有泛型的类里面
高级泛型 规范边界 extends super
Vector
是ArrayList早期版本 底层也是利用(动态)数组来实现的
线程是同步的(synchronized)比较安全但是效率比较低
扩容是2倍的扩可通过构造方法来自定义数组长度
方法和和list里面都差不多
Stack栈类 继承Vector
只有一个无参数的构造方法
特殊的方法
push(E e)将某个元素压入栈顶 --> add()
E =pop()将某一个元素从栈顶取出并删除E = remove()
E = peek()查看栈顶的一个元素不删除 get()
Boolean = empty() 判断栈内的元素是否为空 Boolean = isEmpty()
int = search() 看看给定的元素在栈中的位置indexOf()
Queue接口
子类LinkdList ArrayDeque
通常无参数构造
一般方法
add()
element() 相当于get()
remove()
Boolean = offer(E e);相当于add() 不会抛出异常
E = peek() 查看相当于element()
E = poll() 剪短相当于remove()
LinkedList
底层使用双向链的结构 适用于插入或者删除 不适合遍历和轮询
构造方法 无参的有参的
常用方法 增删查改 add() get() set() size() remove()
手册中的方法
addAll() addFirst() addLast() clear() contains() element() getFirst() getLast()
indexOf() lastIndex()
HashSet
无序无重复 没有set(查询)方法 没有get()方法 可以用增强for循环
无序:指的是我们存放元素和取元素的位置不是一样的
HashSet (底层是HashMap 数组加链表 散列表 临街链表)
方法
boolean add() boolean remove()
iterator()迭代器获取一个迭代对象
无重复原则
先利用equals方法比较
如果我们要让自己写的一个类默认比较的是内容那么我们可以重写equals方法
其次是比较了hashCode方法比较他们的hash值是否相等
两个方法共同作用才出现了HashSet的无重复原则
发现重复就拒绝存入
TreeSet
TreeMap-->二叉树利用Node(左 中 右)
无序无重复
无参构造方法 带collection构造方法
基本常用方法
add() iterator() remove() 没有修改 size();
无重复规则是如何实现的
TreeSet本身是有顺序的是按照Unicode码排序的
但是和我们存放和取出的位置是不一样的
他的排序是通过compaTo来实现的
如果想让自己写的类能存进TreeSet中就必须重写comparaTo方法不能随意的添加
如果发现内容相同就拒绝存入
Map
HashMap存储的是键值泛型是两个<key,vlaue>
key是无序无重复(重写hashCode和equals方法) value是无序有重复的
构造方法有有参的也有无参的
常用方法
put(key, value)(也可以修改) remove(key) replace(key, value) get(key)
Set<key> = keyset()获取全部的key Set<Entry> = entrySet()entry相当于一个节点
key存储的顺序与取得的顺序不一致
key不能相同如果相同的话那就覆盖原来的(与set的相反)
不同的key可以存储相同的value
API中的方法
clear() containsKey() containsValue() getOrDefault(key , defaultValue)(defaultValue是自己加的如果key没有找到才加) isEmpty() putAll() putIfAbsent(key,value)(如果有key就不添加了如果没有就添加进去)
数组和集合什么情况下用
想要存一组元素如果希望存进去的值不变的话就用数组长度不确定的话那就用集合
如果长度不确定的话该选哪个集合
List Set Map
List家族有序的 存储有序的就用这个
ArrayList 适合遍历和轮询
LinkedList 适合插入和删除
Stack 后进先出 (LIFO)
Set家族无重复 如果存储元素希望无重复就用这个
HashSet 性能比起下面更高
TreeSet 希望存进去的元素自动去重复同时还能自动排序
Map家族key-value 希望通过唯一的key快速找到value就用这个
HashMap 性能更高
TreeMap 希望存进去的元素key自动排序
HashMap底层的数据存储结构
散链表结构 数组加链表
HashCode方法 不同的对象可以产生相同的hashCode码 而不同的hashCode码不能产生相同对象
TreeMap
自然有序按照Unicode码排序的
Tree中的key需要可比较的key的对象需要实现comparable接口
底层实现的结构是红黑二叉树
异常
Exception
RuntimeException(运行时异常) 其他异常
异常的分枝体系
运行时异常(非检查异常)
Error和RuntimeException都算运行时异常编译的时候不会被检测
这类异常我们可以处理也可以不去处理(用try throws就可以了)
只要求我们知道错在哪里了和知道怎么修改就可以了
InputMisMatchException 输入不匹配
NumberFormatException 数字格式化
NullPointerException 空指针异常
ArithmeticException 数学异常 10/0 小数/0不会有异常infinity
NegativeArraySizeException 数组长度为负
ClassCastException 造型异常
StringIndexOutOfBoundsException 字符串长度越界了
ArrayIndexOutOfBoundsException 数组越界
IndexOutOfBoundsException 集合越界
IllegalArgumentException 参数不合法
编译时异常(检查异常)
这类异常产生后我们必须去处理不然极有可能导致后续的代码停止
这时候就要求我们取处理异常了 处理异常不代表异常没有了 处理异常指的是处理完该异常后后续的代码能够正常的运行了
处理异常的手段
try{} catch(){} finally{}
try不能单独出现要么跟catch 要么跟finally
catch可以出现很多个
catch(NullPointerException e){}多个异常之间没有等级关系(除了Exception是所有异常的父类他执行了后面的异常就不能执行了)捕获异常只能是从小到大不然报错
final finally finalize
final修饰方法属性变量类是一个特征修饰符
final修饰方法不能被重写
修饰属性必须赋值不然会报错
修饰变量 如果为基本类型的话值不能发生改变 引用类型的话只可以发生变化地址不可以发生变化(如果没有赋初值给一次机会赋值)
finally
是try catch之后的代码块可有可无有且只能有一块
finalize
是Object中的一个protected修饰的方法
对象没有任何指向的时候会被GC回收回收的时候回调用finalize方法
若想看到对象回收的效果可以重写public void finalize(){}
当在方法中有try catch finally 和return时不管return在哪里只要有finally他都要执行然后再把相应的返回值给出去他们三个是一个大家庭
Throws抛出异常谁调方法就抛给谁
throw一定是在方法内产生的 属性(全局变量)是产生不了异常的也处理不了的 块也没有异常
抛出异常也可以抛出几个 与catch类似 抛出异常也是从小到大
自定义异常
自己描述一个异常类 必须要继承异常
如果自定义异常继承--->RuntimeException 则为运行时异常可以处理也可以不处理
如果自定义异常继承--->Exception则为编译时异常那么我们就必须处理了
想要用自己的异常就必须
创建一个自己定义的异常的对象然后用throw关键字主动产生异常
I/O流
在java.io包下面
我们在程序中创建的File他不是一个文件或者文件夹他只是一个对象它和电脑硬盘中的文件只是形成了一个一一对应的映射关系
流指的是数据的流动分为Input(读数据)输入 Output(写数据)输出
File
File不能直接操作文件中的内容只能错做文件本身
File中的常用方法
canRead()是否可读 canWerite()是否可写 isFile()是不是文件(.txt) isDirectory()是不是一个文件夹 isHidden()文件是否隐藏状态 length()文件的长度(字节个数) lastModified()获取文件的最后修改时间毫秒值
String path = getAbsolutePath()获取文件的绝对路径
相对路径 就是前面不加盘符默认是当前工程的路径
String name = getName()获取文件的名字
createNewFile()创建一个文夹要抛异常他可能没有父亲C:\a\Test.java可能没有a文件夹
mkdir()创建一个文件夹单一的
mkdirs()创建多个文件夹
getParent()获取当前file的父亲的file名字
getParentFile()获得当前file的父亲file对象返回值是File
String [] str = list()获取当前文件夹的儿子的名字的
File [] file = listFiles()获取当前file的所有儿子的对象的 只有文件夹才可以调用这两个方法,如果文件调用这个方法的话不会报错数组为null,当前file是文件数组不为空他的长度为0则说明文件夹为空
delete() 布尔类型的删除不了带东西的文件夹,不管文件里面有没有东西都直接删掉不能找回
文件夹的遍历----需要一个递归
查看属性
创建新的文件文件夹
查看父目录
对文件的删除和遍历(通过递归方法)
字节型文件输入流
在java.io FileInputStream继承InputStream类
里面的方法
available()返回从此输入流中可以读取(或跳过)的剩余字节数的估计值
read()读取文件当中的文字一次只读取一个字节
read(byte[] b)一次读取byte数组的长度这么长的字节
skip(long l)跳过多少字节读取
创建文件如果是输入流的时候如果没有那个文件则会抛出FileNotFoundException异常
创建文件如果是输出流的时候如果没有那个文件他不会抛出异常反而会默认帮我们创建那个文件
FileInputStream (读文件) FileOutputStream(写文件)
字符流
FileReader(读文件) FileWriter(写文件)
FileReader
继承 InputStreamReader 在继承Reader
构造方法
常用方法
read() read(char[])
FileWriter
继承InputStreamWriter 再继承 Writer
构造方法
常用方法
write(int) write(char[]) write(String) flush() close()
最常用方法
FileInputStream FileOutStream FileReader FileWriter 方法 read write
缓冲流
在流的过程中增加缓存
让我们使用流读取文字更加的流畅
高级流 通过低级流创建
BufferedInputStream/BufferedInputStream
BufferedReader/BufferedWriter
BufferedReader里面的readline方法有用读取一行
BufferedWriter里面的newLine()是学一行
数组流
byte数组
char数组
数据流
对象流
对象的序列化/反序列化
对象的序列化
将对象拆成字节碎片记录在文件中
对象的反序列化
将文件中的对象碎片反过来组合成一个完整的对象
想要白对象写进文件里去的话
就必须实现Serializable接口
这和接口只是示意性的说明了了一下没有什么实在意义
为了让对象可以反序列化
需要在对象中多存在一个属性
相当于是当前的版本号
线程
程序
可以理解为一组静态的代码
进程
正在运行的程序 静态的代码运行起来
线程
正在程序中的小单元
主线程(系统线程)
用户线程 main
守护线程(精灵线程)GC回收器
线程是操作系统级别的 CPU操作
线程的几种状态
new start CPU分配(run方法) wait exception over
创建线程---à就绪状态---à执行状态---à等待(挂起)---à异常(死亡)
notifiy/notifyall
实现线程的过程
继承了Thread线程重写run方法
new一个线程对象 调用start方法(我们调用run的话就是单线程了) 让线程进入等待状态
实现接口实现Runnable
重写run方法new一个线程对象
生产者消费者问题
当两个消费者同时访问一个仓库中最后一个元素的时候这时有可能出现资源抢夺问题
此时需要加锁 sychronized锁的不是方法是对象谁来调用锁谁
当没有锁的时候有可能会产生一个IllegalMonitorException
程序进程线程之间的区别
线程的创建方式
线程的几种状态 如何切换
sleep wait的区别
类 Thread Object
调用 静态 类名 对象
理解 哪个线程调用 谁等待 对象调用方法 访问对象的其他线程等待
唤醒 不需要别人来唤醒 需要其他对象调用notify/notifyall来唤醒
锁 不会释放锁 等待或释放锁
join方法是Thread类中的方法
让多个线程同步执行变成单个线程
死锁
synchronized一但对象被锁定的情况下没人释放锁其他的对象都需要等待
这是就可能产生死锁的情况
哲学家就餐问题
计时器定时器 线程应用
java.util包 Timer类
无参构造方法
time.schedule()
private ArrayList<String> list = new ArrayList<>();
private int count = 0;
{
list.add("a");
list.add("b");
list.add("c");
list.add("d");
}
public void test() throws ParseException {
System.out.println("预备开始");
Timer time = new Timer();//一个小线程 DATA 延迟
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date firstTime = sdf.parse("2019-10-28 20:05:00");
time.schedule(new TimerTask() {
@Override
public void run() {
for(int i = 0 ;i < list.size();i++){
System.out.println("第"+count+++"次"+"给"+list.get(i)+"发一条信息");
}
}
},firstTime,2000);
}
public static void main(String[] args){
TimerTest tt = new TimerTest();
try {
tt.test();
} catch (ParseException e) {
e.printStackTrace();
}
}
究极版单例模式
private SingleTon(){}
private static volatile(为了防止重排序) SingleTon singleTon;
public static SingleTon getInstance(){
if(singleTon == null){
synchronized (SingleTon.class){
if(singleTon == null){
singleTon = new SingleTon();
}
}
}
return singleTon;
}
反射(reflect)
类 从很多对象中抽取出来的共有的行为特征 抽象描述 用来描述一组对象
对象 从现实生活中存在了好多的对象 很多相同特征 相同行为
类是用来描述一组对象
反射机制则可以理解为用来描述一组类的(与File差不多)
Class 用来描述类本身
Package 用来描述类所属的包
Filed 用来描述类中的属性的
Method 用来描述类中的方法的
Constructor 用来描述类的构造方法的
Annotation 用来描述类中的注解的(@Override)
获取类的方法
Class c = Class.forName(“包名.类名”);
(可以直接通过Object object = c.newInstance建立一个无参构造方法只能是无参)
Class c = 类名.class;
Class c = 对象.getClass();这是Object类中的方法(String str = new String(“java”);)str.getClass();
Class类中的常用方法
int modifier = getModifieras();获取权限修饰符和特征修饰符的
String name = getSimpleName();获取类名字的
String name = getName();获取类全名的包括他所属的包
Package p = getPackage();
p.getName();
Class clazz = getSuperClass();获取父类
Class[] classz = getInterface();获取接口的
Field中的常用方法
int = Modifiers()
Class = getType()
String = getName()
Class clazz = Class.forName("refleckt.Person");
Field field = clazz.getField("name");//知道属性的名字
Field [] field = clazz.getFields(); 不知道里面的属性就直接获取全部的属性包括继承父类的属性都一起列出来 只能获取公有的
int a = field.getModifiers();
System.out.println(a);
Class s = field.getType();
System.out.println(s.getSimpleName());
System.out.println(s.getName());
System.out.println(field.getName());
反射操作String里面的private final 数组;
String str = new String("abcdefg");
Class clazz = str.getClass();
try {
Field field = clazz.getDeclaredField("value");//只能获取本类的所有属性不能获取父类
field.setAccessible(true);
char [] c = (char [])field.get(str);
c[0] = '你';
c[1] = '我';
System.out.println(str);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Class [] = getClasses();获取内部类
操作方法
Method [] method = clazz.getDeclaredMethods();
System.out.println(method1.getModifiers());//修饰符
System.out.println(method1.getReturnType().getSimpleName());//返回值名字类型
System.out.println(method1.getName());//方法名字
Class [] cc = method1.getParameterTypes();//获取参数列表的类型
Class [] exception = method1.getExceptionTypes();//获取异常的类型的
(可以有返回值) = (String) method1.invoke(p,"类型(Integer String Double)");
注解
注解的写法@xxx[(信息)]
注解放在哪里 类上面 属性上面 方法上面 构造方法上面 参数前面
注解的作用
充当注释的作用(仅仅是一个文字说明) @Deprecated
用来做代码的检测(验证) @Override
可以携带一些信息(内容) 文件.properties .xml 注解
java中有一些人家写好的注释供我们用
@Deprecated 说明方法已经废弃了
@Override 用来做代码检测 检测此方法是否重写
@SuppressWarnings(信息) String[] 数组 unused变量定义后未被使用 (serial)序列化
rawtypes(没有泛型) unchecked(出现了泛型问题) all是直接取消所有的非语法错误
Properties pro = new Properties(); java.util下想map集合他读取的是.properties文件
try {
pro.load(new FileReader("src\\Test\\test.properties"));
// String name = pro.getProperty("key1");
// System.out.println(name);
Enumeration en = pro.propertyNames();//得到的是key
while(en.hasMoreElements()){
String key = (String) en.nextElement();//遍历的是key
String value = pro.getProperty(key);
System.out.println(key+"---"+value);
}
注解中可以携带信息可以不携带
信息不能随意的写只能是以下的类型
String Enum 基本数据类型 注解类型 数组类型[] 数组里面只能是如上的几种类型
如何自己创建一个注解
通过 @interface 定义一个性的注解类型和接口有点象
属性都是public static final的属性
如何自己描述一个注解类型
通过@interface定义一个新的注解类型
写法与接口非常的相似
属性是用public static final 来修饰的
方法是用public abstract 来修饰的但是方法必须有返回值
自定义元注解如果像要使用
就要细致的说明(利用元注解)
@Target描述自定义注解可以放在哪里
@Retention描述当前的注解的作用域
源文件à编译à字节码文件à加载à内存执行
SOURCE CLASS RUNTIME
@Inherited描述当前的注解是否能被子类继承
@Document 描述这个注解是否能被文档所记载
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Docment;
@Target({TYPE,CONSTRUCTOR,FIELD,METHOD})描写可以放在哪里
@Retention(RetentionPolicy.RUNTIME)描写作用域
@Inherited
@Document
public @interface MyAnnotation {
String test();
}
自己使用自己描述的注解
问题一.
在注解里面描述了一个方法 方法没有参数 方法是返回值String [] 使用的时候让我们传递参数 可以理解为 注解的方法做事将我们传递的参数搬运走了给别人
问题二.
使用别人定义好的注解我们不用写方法名我们自定义的要写方法名= 是怎么回事呢
是因为别人定义好的注解里面只有一个方法 它写成value就可以不用写方法名=
如果我们自己写的注解要想不用写方法名= 的话也可以把方法名改为value 但是如果有一个以上的方法了就必须写方法名= 别人的也是public class TestAnnotation {
@MyAnnotation(test = "aaa")
private String name;
}
如何获取注解里面的内容
Class clazz = Person.class;
Field field = clazz.getDeclaredField("name");//获取属性
Annotation annotation = field.getAnnotation(MyAnnotation.class);//获取Annotation的类型
Class aclazz = MyAnnotation.class;//获取Annotation的类型(annotation.getClass)
Method method = aclazz.getMethod("value");
String values[] = (String[]) method.invoke(annotation);
for (String value : values) {
System.out.println(value);
}
低级Spring(之ioc)
GUI(窗体,菜单,面板组件)
AWT Swing
窗体 Frame JFrame
Panel Panel
Button JButton
TextArea JTextAre
Lable JLable
TextField JTextField
JMenubar菜单条
JMenu菜单
JMenuItem菜单项
frame最大的窗体管理方式边界式中东西南北 BorderLayout
JMenuBar 菜单条 上面frame. set JMenuBar (bar) ;
Panel 面板可以有多个 管理方式流式居中 FlowLayout
组件
frame. setLayOut (new FlowLayout () ;
frame. setLayout (null) ;|
事件 ActionListenter KeyListener MouseListener Windos Item…
第一阶段
数据库
MySQL
操作数据库的语言规范
SQL接过话查询语言(关键字不区分大小写,最好大写)
DDL数据定义语言
用来创建,删除,修改数据库中的对象(create创建,drop删除,alter修改)
DML数据操作语言
用来操作数据库表格中的具体数据
写数据,增(insert),删(delete),改(updata) 创建数据库create
读数据 查(select) à
DQL数据查询语言
select where(条件) group by(分组) having(条件) order by(排序)
DCL数据控制语言
用来控制用户权限的 SYSDBA数据管理员
(赋予权限)grant 权限,权限 to 用户
(回收权限)revoke 权限,权限 from 用户
TPL事务处理语言
(可以理解为多线程并发访问同一个文件带来的安全问题)
begin transcation启动一个事务一般oracle mysql是自动的
操作 commit提交 rollba回滚 save point A保存还原点
数据库安装完成之后
在命令行输入show databases;之后看自己又几个数据库分号必须加不然认为没有输入完
想要用那个数据库就用use xxx 就可以使用那个数据库了
用show tables;显示当前数据库的表格
MySql相当于一个小小的服务
先启动服务器localhost开放一个端口3306
卸载数据库
停止服务 卸载产品 删除注册信息 运行à 输入à regedità 选择HKEY_LOCAL_MACHINEà SYSTEMàControlSet(有几个)开头àMySql和EventLog(ApplicationàMySql)
MySql不区分大小写 创建一个表格create
创建数据库
creat table 表名(列名,类型(长度), 列名,类型(长度), 列名,类型(长度));
数据库存储的数据
存储数据的方式来分类大致可以分为三类:
数值型
整数 tinyint smallint mediumint int/integer(4字节32个比特位) bigint
小数float double decimal numeric前面两个要精确一些(m,n)一共m为小数点后n位(m默认10,1-65)(n默认0,0-30)
字符串
char字符串(不可变动)(char (4) 规定是4字节了就算你写的是’a’前面也是3个0)
varchar可变字符串 varchar(4) 你只写了’a’自动是占用一个字节
variable可变的
binary二进制
varbinary 可变二进制
blob二进制大文本
text正常大文本
日期/时间
date日期 time时间 datetime时间&日期 timestamp时间戳(详细是时间年月日)
在自己的database中建立一个表格
用来记录学生的信息---Student
学号 姓名 性别
通过DDL来修改表的结构
修改表格的名字 alter table 原表名 rename [to] 新表名
修改原有的列(修改表格的列名 类型 长度 )
alter table 原表名 change 原列名 新列名(其他可以改可以不改其他一样)
新增一列
alter table 原表名 add 新列名 类型 长度
删除原有的列
alter table 原表名 drop 要删除的列名
删除表格 drop table 表名
删除database(数据库) drop database 数据库名字
新增记录
insert into 表名(列名…) values (值…);
insert into 表名 values (值…);可以省略列名就是插入全部信息
insert into 表名 values (值…),(值…)…;可以一下增加几个记录
创建数据库的时候可以默认字符集
create database 数据库名 default character set = ‘utf8’;
insert into student values () default character utf8 collate 排序效果;
排序效果utf8_general_ci utf8_unicode_ci
如果不知道自己使用的是什么字符集的话
select 列 from 表 where 数据库 = ‘自己数据库名字’;
select schema_name,default_character_set_name from information_schema.schemata where schema_name = ‘数据库名字’;
查询记录
select 列名 … from 表名 where…
删除记录
delete from 表名 where….
修改记录
update 表名 set 列 = 值,列 = 值,where…
查看数据库的状态
show table status from 数据库名 like ‘表名’;
条件筛选where
除了insert后面不加where delete updata select之后都可以加上where
delete from 表名 where…
updata 表名 set 列 = 值 where…
select 列 from 表 where…
选出来的是符合条件的行 不是列
按照某一列后者某一条件来筛选的
(not)between A and B包含AB
select * from 表名 列名 (not) in (a,b);满足ab的条件
like 模糊查询 后面经常跟上 %(0到多个) _(有且仅有一个)
排序 order by 升序排列(默认是asc) 降序排列(desc)
数据库常用函数
比较函数
ifnull(值) 空就返回1 不空就是0
数学函数abs绝对值 floor向下取整 mod(5,2)5对2取余 pow()求次方 round四舍五入
日期时间类
now() year(date数据) month(date) day(date)
控制流程函数
if(条件,值1,值2),满足就是值1不满足就是2
ifnull(值,v)如果为空就是v不是空就不管
字符串函数
length() concat(字符串拼接) substr(截取) instr(str,’a’) replace() upper(大写) lower(小写) ltrim(去左空格) rtrim(去右空格) lpad() rpad()
reverse(反转)
distinct去重
distinct 列,列…如果后面跟上了几个列那他就是组合几个列来看的一列和二列是一样的
话就去重复
分组函数
count(字段(*))记录个数 *是指的一行只要有东西就记录
max() min() avg() sum()
where > group by> having(小where)>order by
嵌套查询
嵌套可以将一个查询语句当成另一个查询的条件
可以将上一次的查询结果当作下一个查询语句的表格
可以联合几张表格的东西只要有联系
几个关键字的使用
in满足查询子集中的某一个即可 默认=比较in后面的子集内可以是常量可以是表达式
以下三个后面只能跟一个表的式子不能跟一个固定的值
any 满足子集中的一个即可>any <any =any !=any
some 与any用法一样的
all满足子集中的全部才行
集合操作
并集union
要求要查询的前后两个列数是相等了
类型没有要求,列名默认是前一个子集的名字
union和union all的区别
union合并后可以去重复 性能较慢去重后的元素是第一个后面的就不让他出现
union all是直接合并元素不去重性能快
列的约束
主键约束
每一个表格内只能有一个列为主键
主键通常是用来表示表格中的数据是唯一存在的
主键约束当前列不能为null值
主键约束要求当前列值是唯一存在的不能重复
添加约束语句
alter table 表名 add constraint 约束名字 约束类型(列);
alter table student add constraint pk_myclass primary key(id);
alter table 表名 add constraint (主键名字) primary key(列);
constraint可以不要
设置主键之后可以设置主键的某些特性
主键自增alter table 表名 modify 列名 int(4) auto_increment;没有值就默认是1
alter table 表名 change 列名 列名 修饰符(多少位) auto_increment;
alter table 表名 auto_increment = 值;就从值开始自增1
去掉自增约束 alter table 表名 modify 列名 int(4);
去掉主键约束 alter table 表名drop primary key;但是非空特性还在
看key的方式 desc 表名;
show keys from 表名;
唯一约束
可以为表格中的列添加唯一约束
他的值可以为空但是不能重复
他可以位多个列添加约束
alter table 表 add constraint 约束名 约束类型 (列)
alter table student add constraint uk unique key (id);
简写alter table student add unique [key](id);
删除 alter table 表 drop index 约束名
非空约束
alter table 表 modify 列 int(4) (not) null ;
alter table 表 modify 列 int (4) not null;
alter table 表 modify 列 int(4) not null default 值;设置默认值
检查约束
外键约束
约束自己表内的信息不可以乱填
受到另一个表格某一列的影响
可以有多个列被设置可以重复可以为空
当前列的值受到另一张表格某一列的影响
另一张表是唯一约束(主键 唯一)
alter table 表 add constraint 约束名 foreign key (列) references 另一个表 (列);
alter table 表 add foreign key (列) references 另一个表 (列);
删除外键约束alter table 表 drop foreign key 外键名字;
执行上述语句其实外键已经被删除了
但是系统会自动生成一个key 名字和外键一样的需要自己手动删除
alter table 表名 drop key 名字;一般是删除外键的key
看key的语句
show keys from 表名
desc 表名
show create table 表名;
关系
一对多 一端有一个主键 多端保证一个外键与外表关联
多对多 一般是两个主表然后一个中间表来实现主表与主表之间的关系
一对一 在一对多的基础上来实现的 可以将多端的主键设置为外键
表格之间的联合查询
广义笛卡尔积à等值连接
竖着的列是两个表格列之和
横着的行是两个表格行之积
将两张或者多张表格连接起来没有条件约束任何的表都可以
select * from A ,B where 条件
外连接
select * from A left/right [outer] join B on条件
A B先后顺序是由他们谁在左谁在右决定的
left和right是用来控制基准的谁在select * from A left/right [outer] join B on条件
以A为基准反之亦然
然后后面一个表格就是取决于on后面的条件了有就显示没有则为空
内连接(自连接)
select * from A a inner join B b on 条件 where a = b;可以加上where
行列互换
select wname 仓库名,sum(if(wmonth=1,wstorage,0)) 一月,sum(if(wmonth=2,wstorage,0)) 二月,sum(if(wmonth=3,wstorage,0)) 三月 from warehouse group by wname; sum可以是其他函数但是运用得合理
分页查询
语句完成之后 à limit a,b 显示的起始位置[0,..]
DCL数据控制语言
控制用户的权限
grant赋予
remove回收
创建新的用户 给新的用户赋予权限 注销用新的用户登录 回收用户权限 创建新的用户
Mysql配置环境变量
登录MySql mysql –u root –p 回车输密码
在mysql数据库中 user表格 里面的user列 host列 password列 更新版本在authentication_string列可以看见用户相关的信息
mysql创建新用户
create user ‘用户名’@‘ip’ identified by ‘密码’; ip可以是localhost(本机) 也可以是*(表示所有的ip都可以访问)
create user ‘admin’@’localhost’ identified by ‘123456’;
当前的权限是Usage只允许登录不能干其他的
show grants for ‘用户名’@’ip’; 查询用户的权限
赋予权限:grant 权限 on 数据库名.表名 to ‘用户名’@’ip’;
grant all on *.* to ‘用户名’@’ip’;
然后最好刷新一下:flush privileges;
回收权限
revoke 权限 on 数据库名.表名 from ‘用户名’@’ip’;
修改用户的密码
update user set authentication_string=password(‘密码’) where user = ‘用户名’;password是加密函数
删除用户
drop user ‘用户名’@’ip’;
数据库设计的范式
目的是减少数据库的冗余
管理变得简单了
查询的时候性能可能不太好
Normal Form(标准化形式----普通范式)
1NF
数据原子性
每一个表格的每一个列都是不可分割的
在行列的交叉点是不可以存在两个数据的不然违背了第一范式
必须要有主键
2NF
在满足第一范式的条件下
非主键不能受到主键(或者主键一部分)的影响 如果影响了就拆分表格
3NF
在满足前两个的前提下
不允许出现传递依赖性(非主键列不能受到主键或者主键列一部分的影响和非主键列的影响)
出现了此类问题就拆开
事务的处理
实质上就是多线程并发操作一个数据库产生的安全问题
事务的四大特性(ACID)
A(Atomicity) 原子性
一个事务中的所有操作是一个整体不可分事务中的所有操作要么都成功要么都失败
C(Consistency) 一致性
一个用户操作数据后另一个用户看到是数据与他之前看到的数据是一致的
I(Isolation) 隔离性
一个用户在操作数据库的同时另一个用户不能干预多个用户之间的数据事务操作要相互隔离
需要考虑到事务的隔离级别
Serializable 级别最高可以避免所有出现的的问题 性能很慢
Repeatable Read 可重复读 (一次会话内永远读到的是一样的) (MySql默认管理级别)
即使是数据库已经删除了这个数据(只要没有commit都一样)
Read Committed 只能读已提交没有提交的不能读 (避免脏读) (Oracle 默认管理级别)
Read Uncommitted 读取未提交 (所有的效果均无法保证)
修改数据库的管理级别
set session transaction isolation level 级别;设置会话事务隔离级别
查询级别:select @@tx_isolation;
数据库读取出现的问题
脏读:一个用户读到了另外一个用户没有提交的数据
A修改了数据还没有提交B读到了,然而A不提交数据回滚回来B读到的就是无用数据
不可重复读
A先读取了数据,然后B对数据进行了修改,A再按前面的条件读一次与第一次读到的不一致了(一个事务里面)
幻读(虚读)
A先读了一些数据,然后B又增加了记录A按照前面的条件再读一次发现与原来不一致
D(Durablity) 持久性
指的是用户提交数据之后他对数据库底层是真实存在的不可以变的是永久保存的不可返回
mysql数据库事务管理默认的效果可以更改
autocommit = on;
show variables like ‘%commit%’;
show variables like ‘autocommit’;
set autocommit = off;
开启事务 begin; 和 start transaction;
开启一个事务
每执行一条语句之前都会默认开启事务
执行操作
各种语句可能不止一条
事务的处理
提交(commit)/回滚(rollback)/保存原点 mysql 会默认提交事务
show create table bank;查询表格的字符集
alter table bank convert to character set utf8;修改已经建好的表或者数据库的字符集
JDBC
JDBC-ODBC 每一个客户机都需要安装 很耗费空间管理方便
JDBC-Native 类是第一种每一个客户机安装调用原生C/C++具体到某一个数据库
JDBC-Net 使用了标准的Socket通信不需要每一个客户机都进行安装相对比较灵活
纯的JavaJDBC 一个纯粹基于Socket不需要安装在客户机上每一个数据库每一个数据库的厂商自身提供可以下载
先找到适合MySql的JDBC驱动包
下载一个驱动包
JDBC六部曲
导包
加载驱动类 Driver
获取连接
创建状态参数
执行数据库操作
写 DML DELETE INSERT UPDATE(对数据库进行更新操作)
读 DQL SELECT(数据库没有发生变化 需要处理结果)
关闭 先创建后关闭
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args){
// JDBC六部曲
// 1.导包
// 2.加载类驱动
try {
Class clazz = Class.forName("com.mysql.jdbc.Driver");
// 3.获取链接 DriverManager管理者
String url = "jdbc:mysql://localhost:3306/test01?characterEncoding=utf-8"; //要连接那个数据库 jdbc:mysql://ip:port/database名字
String user = "root";
String password = "123456";
Connection connection = DriverManager.getConnection(url,user,password);
// 4.创建状态参数
Statement statement = connection.createStatement();
// 5.执行操作(增删查改)
//String sql = "delete from bank where id = 7";
String sql = "insert into bank values (7,'郭雨衡',99999999)";
statement.executeUpdate(sql);
System.out.println("执行成功");
// statement.executeUpdate(String); ?=statement.executeQuery(String);
// 6.关闭 倒着关闭
statement.close();
connection.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
JDBC 5.0 导包àcom.mysql.jdbc.Driver
JDBC 8.0 导包àcom.mysql.cj.jdbc.Driver
5.0 url àjdbc:mysql://ip:port/database名字
8.0 url àjdbc:mysql://ip:port/database名字?serverTimezone=CST
加载驱动的目的就是让静态方法执行一次(静态元素在类加载的时候就产生了)
加载驱动的方法
Class.forname(String);
new Driver()
DriverManager.registerDriver(new Driver());
System.setProperty(“jdbc.driver”,” com.mysql.cj.jdbc.Driver”);
他们的目的就是为了加载驱动
可以自己设置手动提交事务
连接.setAutoCommit(false); true是自动提交
设置隔离级别
连接.setTransactionIsolation(Connection值);
连接.commit()提交
SavePoint s = 连接.setSavepoint(“xxx”)
连接.rollback(s)回滚(回滚到还原点,可以不加s)
SQL注入问题
用Statement很不安全容易被别人随意**
所以利用PrepareStatement(预处理状态参数)
Statement和PrepareStatement区别
Statement PreparedStatement
普通的状态参数 预处理状态参数
创建时不需要sql语句 创建时需要预先加载sql语句
此时没有执行sql 创建时没有执行但是在底层已经准备好了我们
所需要的sql查询结果性能高可以利用动态化进
行参数的处理利用?替代数据类型及值
PrepareStatement好处
MVC
V:View视图层
M:Model模型层 (数据的处理service,数据的读写dao,数据的存储domain)
C:Controller控制层
协议
当想浏览器地址栏中输入一个url回车之后,网络中都会发生什么
先看浏览器的缓存 如果浏览器认识就直接告诉你ip是什么
如果不认识 看本机host文件Windows C:windows/system32/drivers/etc/host
如果还是没有的话就会看自己家里的路由器
如果还是没有的话就继续访问上级路由/城市的DNS
层层递进globalDNS
也可能是直接通过域名直接访问ip
http协议分为两个部分
请求头 + 要搜索的东西
http协议分为两个部分:
请求Request
请求方式(GET,POST) 路径 协议版本
TCP/IP协议(对方的ip自己的ip对方的端口) HTTP协议(请求头)+要搜索的东西
Request
请求头和数据体
请求方式 url http协议版本
GET/POST /路径?url 协议版本
HOST:www.baidu.com(连接的网站)
Connection:keep-alive长连接
User-Agent:代理各个浏览器的详细信息
如果是post的话这里就是他传输的文件的信息get一般不传输文件
请求方式GET/POST DELETE/PUT/HEAD(不常用)
响应Response
响应头 数据体
协议版本 状态码 信息
HTTP/1.1 200 OK
Cache-Control:缓存
GET和POST的区别
- 基于什么前提的?如果没有前提不适用任何的规范,值考虑语法和理论的HTTP协议他们没有区别只是名字不同
- get和post如果是基于RFC规范的
- 理论上(Spacification):get和post具有相同的语法,不同的就是get是用来获取数据的post是用来发送数据的
- 实现上的(implementation):各种浏览器各种浏览器就是这个规范的实现者
常见的不同
1).get数据在url是可见的,post请求不显示在url中
2).get是对长度有限制的 post对长度是没有限制的
3).get请求的数据可以添加为书签,post请求到的不可以添加为书签
4).get请求道的数据按后退刷新不会受到影响,post则会重复提交
5).get编码类型:application/x-www-form-url
post编码类型有多种:encodeapplication/x-www-form-urlencoded
:mulitipart/form-data
6).get历史参数会保留到浏览器中,post不会
7).get只允许ASCII post没有编码限制允许发二进制的
8).get与post相比,get安全性相对较差,因为所发的数据是url的一部分
Cookie和Session区别
Cookie(存放在浏览器客户端上的)
当登录网站之后,网站会自动记住这个cookie,以后每次每一次向浏览器发送请求它都会自动带上这个cookie,服务端看到这个代有id的cookie就可以解析这个加密的id了,从而获取这个id,如果能获得本身的id那就证明这个用户已经登陆了,后端会继续保留用户信息,cookie是存储在浏览器上面的不是存储在某个页面上的,是可以长期存储的,cookie即是存放在浏览器里面,也是存放在不同的域名下的(每一次请求都会向后端发送的不会因为某个页面的关闭而关闭,不能跨域存储)
缺点就是如果有人知道了这个cookie他就可以在他的电脑登录了
Session
存放在服务器上的缺点:如果用户量非常的大服务端会非常的耗费资源
用户执行登陆操作之后,在那台机器上执行的就一般存在与哪台机器上
B/S结构 Browser只负责展示内容Server负责提供内容
C/S结构 Client只负责展示内容 Server负责提供内容
页面的本质就是字符串 就是带html格式的字符串
浏览器向服务器请求一个页面的本质是什么
服务器接收到请求后,把这个页面内容(带有html格式的字符串)返回给浏览器,页面的内容存在那里存在html文件里面 服务端读取文件将取出来的内容返回给浏览器 最后返回的是一个字符串 这个字符串的来源可能是缓存可能来源于数据库……等等
服务器:严格的来说服务器就是一台计算机,这台计算机只提供服务(不是用户用的计算机一般是linux,unix系统)
我们常常说的服务器其实就是一个服务容器不是真正的服务器
服务容器是一个程序用来监听一个端口,读取文件并且返回,如果我们想通过访问服务器的方式来访问自己的页面我们就得装一个服务器的程序
打开网页的方式:
直接在地址栏中输入网址 在浏览器控制台输入location.href=”网站”回车也可以但是页面会跳转
代有src的标签请求时可以发出的服务器是可以处理的也是可以返回的但是返回之后能否被应用还得取决于浏览器
带有href的标签请求是可以发出的服务器是可以处理可以返回的但返回之后是否被应用还得看浏览器
带有action属性的标签例如form标签也可以发送请求但是他要跳转页面
Ajax既可以用代码控制也可以得到返回及后继续用js处理页面也不会跳转
跨域访问资源:
Js算资源可以跨域访问 ,css文件,jpg png等都可以跨域访问,src的资源都是可以被跨域访问的href的资源大部分都是可以被跨域访问的
那些算跨域访问资源
后端接口的数据
其他域的cookie
其他域的缓存
什么算其他域
页面本身有协议 域名 端口
http://www.baidu.com:80/.....地址
只要其中一个不相同就算跨域访问,跨域发生在浏览器端
跨域这个行为发生在那里
即使(协议 域名 端口号有一个不一样)他也是可以发送请求的
服务器是可以接受的也是可以处理的也可以返回的
浏览器是可以接受的但是接收到之后浏览器发现页面的域和请求的域不一样就会判定为跨域 我们的代码在这里等着但是浏览器判定跨域了所以不会把结果返回给我们的代码
如何解决跨域问题:
后端配合我们进行跨域
- JSONP
- 后端设置Access-Control-Allow-Origin属性可以跨域
后端不支持我们跨域
Ifram(只能显示不能控制)
通过后端代理(自己的后端)
Servlet
初识Tomcat
实际上是一个web容器
一般通用的web容器
Tomcat Apache开源的
Jetty 轻量级的
Resin Caucho公司的
JBoss Weblogic WebSpher
Tomcat是Apache开源的免费一个容器
用来管理web项目 包括Servlet Html+css+JavaScript
Tomcat发展历程
Tomcat6 JDK1.5 Servlet2.x EL2.X JSP2.X
Tomcat7 JDK1.6 Servlet2.x EL2.X JSP2.X
Tomcat8 JDK1.7 Servlet3.x EL3.X JSP2.X
Tomcat9 JDK1.8 Servlet4.0 EL3.0 JSP2.3
Tomcat文件结构
Bin目录 服务器启动相关
*Conf 配置文件 主要(web.xml(请求相关) server.xml(容器自身的信息 比如端口))
Lib文件 jar形式的包
Logs 日志信息
Temp 临时文件
*Webapps 用来存放部署在容器里面的项目资源
*work 用来存放解释jsp后的java文件
Tomcat可以找到文件资源(.html .jsp…)
Tomcat也可以找到操作资源(java代码)
V:View 视图层 Html css js
C:Controller 控制层 HttpServlet
M:Model 模型层
数据处理 service
数据读写 dao
数据存储 domain
D:DataBase Mysql
如何使用Tomcat
- 编写一个自己的类
- 继承Tomcat中的HttpServlet
- 重写一个方法void service(HttpServletRequset,HttpServletResponse) throws ServletExcption,IOException
- 填写web.xml配置文件 目的请求名字真是类对应关系
配置<servlet>
<servle-name>xx与下面对应</servle-name>
<servlet-class>包名.类名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>xx与上面对应(随便写)</servlet-name>
<url-pattner>/请求名字<url-pattner>
</servlet-mapping>
小知识点:发送请求的时候只写工程名字,不写资源名
Tomcat需要参考web.xml配置文件优先参考工程中的web.xml文件,如果没有的话就去找tomcat下的conf下的web.xml文件
当用(IDEA)Tomcat部署项目的时候项目会给你部署到IDEA下你的out文件下并没有给你部署到Tomcat的webapps下,IDEA觉得这样浪费时间只是给了一个映射过去但是可以自己修改部署到Tomcat的webapps中
解析JSP中的java代码后会放到Tomcat中的work内部
请求发送方式:
Get 在浏览器输入url点击回车 <a href=””> <form method=”get”>
Post <form method=”post”>
JSP内置对象:
< % %> 放在_jspServlet内部
<%= %> 放在_jspServlet内部一般赋值
<%! %> 放在_jspServlet外部
<%@ %> 放在作说明一般放在头部
JSP九个内置对象:
HttpServletRequest request
HttpServletResponse response
JSPWriter out
HttpSession session
ServletContext application
Object page
Exception exception
ServletConfig config
PageContext pageContext
HttpServletRequest
String value = request.getParameter(“key”);获取请求携带的参数
Request.setCharacterEncoding(“UTF-8”);
Request.setAttribute(key,Object);
Request.getAttribute();
RequestDispatcher rd = Request.getRequestDispatcher(“index.jsp”);
Rd.forword(request,response);转发
转发和重定向的区别:
转发 重定向
RequestDispatcher类 HttpServletResponse类
Rd.forword(req,resp); resp.sendRedirect(path)
转发是在服务器内部完成的 让浏览器再发一个请求,浏览器是知道的
浏览器不知道
Req和resp是原来的那个 req和resp是新的
地址栏url不会跳转到其他的文件资源(**.jsp) 地址栏url会发生变化
转发只能在服务器当前的工程 可以发送给不同的服务器和新的工程
HttpSession session
Session.setAttribute(“”,obj); obj = session.getAttribute(“”);
Session.removeAttribute(key); Enumeration = session.getAttributeNames();
Session默认存活时间1800秒=30分钟
session.setMaxInactiveInterval(int 秒);设置session的会话时长 但是session对象还在
session.invalidate();设置session死亡对象没有了
ServletContext servletContext = request.getServletContext();//获取ServletContext对象
String v = (String) servletContext.getAttribute("key");//得到key
servletContext.setAttribute("key",obj);//设置key
String v = servletContext.getInitParameter("key");
<context-param>
<param-name>key</param-name>
<param-value>value</param-value>
</context-param>
System.out.println(servletContext.getRealPath("/"));获取真实的路径,web部署的路径
最好的是pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("路径"));
Object page获取当前页对象 index_jsp.java类对象
PageContext pageContext 当前上下文对象
pageContext.setAttribute pageContext.getAttribute pageContext.removeAttribute
作用域对象
PageContext pageContext 只有在当前页作用域内可以访问(xx_jsp.java)
HttpservletRequest request 在一次请求范围之内
HttpSession session 一次会话同一个人(几次请求)
ServletContext application 全局范围,很多的session可以共享
JSP标签
JSP指令标签 用户还没用的时候就已经加载了几个jsp和为一个 可能出现重名
<%@ xxx%> 通常放在jsp头部,做说明性质的描述
<%@page contentType=”text/html;charset=UTF-8”告知浏览器解析时遵循的规则
PageEncoding=”UTF-8” 告诉tomcat解析的时候遵循的字符规则
浏览器解析class文件写回的消息 charset àpageEncoding
Import=””导包
isErrorPage=”true”是一个错误页
errorPage=”xxx.jsp”出错误跳转哪个页面
%>
<%@ taglib%> JSTL
<%@ include%> 用来在当前jsp中引入已经写好的资源,引入html可能乱码
<jsp-config>
<jsp-property-group>
<url-pattern>*.html</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
Web.xml里面配置
Jsp代码标签
<%! %>
<%= %>
<% %>
Jsp动作标签 是在用户用的时候才加载
用来替代jsp标签中java创建对象 对象的取值赋值 请求转发 携带参数
<jsp:xxx>
<jsp:useBean id="user" class="domain.User" scope="request"></jsp:useBean>
创建对象 scope是范围
<jsp:setProperty name="user" property="name" param="name"></jsp:setProperty>
property属性名字(类名) parame是参数名字(请求的参数名字)
<jsp:setProperty name="user" property="*"></jsp:setProperty>
如果属性名字和参数名字一样的property设置为*
EL
${xxxScop.xxx}
${requestScop.xxx}
${sessionScop.xxx}
${param.xxx}//相当于${requestScop.xxx}接收请求携带的参数的
上述都可以用${xxx}简写来接收,但是他会扫描4个作用域速度比较低,
4大作用域(page,session,request,application)
JSTL
先导包
核心标签库:core前缀c
<%@taglib uri=”http://java.sun.com/jsp/jstl/xxx” prefix=”x”%>
<c:out value=””></c:out> 可以写字符串也可以写el表达式
<c:if test=””></c:if> 只能写表达式
<c:choose>
<c:when>
<c:otherwise>
</c:choose> (相当于switch)
循环的时候是个数字${i.index}
<c:foreach var=”user” item=”${requestScop.userList}”>${user.name}…</c:foreach>
<c:forTokens var=”” items=”a-b-c” delims=”-”(按照什么来拆分)>
函数标签库:functions 前缀 fn
<%@taglib uri=”http://java.sun.com/jsp/jstl/xxx” prefix=”xxx”%>
${fn:xxx}
自定义jsp标签
自定义函数
通常是带有返回值的,修饰符必须是静态的.
文件上传与下载
//factory.setRepository(new File());设置缓冲区路径 默认是在tomcat的tem下
//factory.setSizeThreshold(int);设置缓冲区大小 默认大小10240
//fileUpload.setFileSizeMax(long);设置单个文件上传大小
//fileUpload.setSizeMax(long);设置上传总文件大小
HttpFilter
继承HttpFilter只有在tomcat9版本才能继承
之前的版本可以实现Filter接口
重要方法: doFilter init destroy
三个参数:HttpServletRequest HttpServletResponse FilterChain
异常:ServletException IOException
配置:只需要把servlet改为filter
执行servlet之前先过滤
session.setMaxInactiveInterval(int);设置session的最大活跃时间
filter拦截器,默认的是REQUEST,不会拦截forward,会拦截redirect想因为forword是在浏览器内部的请求,但是redirect是新的请求
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>//默认拦截
<dispatcher>FORWARD</dispatcher>//
</filter-mapping>
Listener监听器对象
监听域对象的产生和销毁
监听与对象的值修改删除
Page request application session
Xml
1.写法
创建一个文件 .xml
建议在文件的第一行 头信息
<?xml version="1.0" encoding="UTF-8" >
2.规则
结构良好的 有规则 标签对应 <xxx></xxx>
结构有效的 在结构良好的基础上遵循很多规则(写什么标签 名字叫什么 属性叫什么 几个 顺序)
如果想要让写完的xml遵循结构有效的
需要单独再写一个xml文件--->用来描述规则(类似元注解的作用)
.tld Tag Library Definition 用来描述标签的
.dtd Document Type Difinition 文档类型描述
.xsd Xml Schema Definition 用来描述xml文档内容
.xml eXtensible Markup Language 用来存储数据的文档
3.基本xml文件写法
为了让xml文件中的内容遵循某些规则
自定义dtd
第一可以写在当前的xml文件中
第二可以写在一个外部的文件中 引入
描述根标记
<!DOCTYPE school [规则]>
描述根标记中的其他标记<标签>
<!ELEMENT 元素名 类别|(元素里面的内容) >
类别 通常是EMPTY
元素内容 (其他标签,其他标签)
标签内部没有标签 是普通的文字 PCDATA
PCDATA Parsed Character DATA(通常用来描述标签中间的文字<>xxx<>)
可以被解析的字符数据 支持实体 &xxx;
>大于 <小于 &与符号 "双引号 '单引号
正常情况下 描述标签内部的子标签时候 默认认为是一个
还需要在子标签基础上增加一个 对于个数的说明
*符号 0-n个 ?符号 0-1个 +符号 1-n个
,符号 都有 |符号 a或b其中的一个
每一个标记中还需要有属性
<!ATTLIST> attribute list
<!ATTLIST 标签名 属性名 什么类型 值>
通常类型的描述
CDATA Character DATA 原封不动 (通常用来描述属性名)
(t1|t2|t3) 来描述
通常值的描述
默认值 "xxx"
值的说明 (是否是必须 固定的。。)
#REQUIRED必须 #IMPLIED非必需 #FIXED value固定的
如果想要描述实体
<!ENTITY 实体名字 "实体的值">
<!ENTITY spring "this is spring">
<div>&spring;</div>
Web注解
使用在Filter,Servlet,Listener上
WebFilter,WebServler,WebListener
Exp:WebFilter(“/test”)èWeb(urlPattern=”/test”)è
WebFilter(value=”/test”)
èWebFilter(urlPattern=”/test”)èWebFilter(urlPattern={“/test”,”/xxx”,…})
一个请求可以省略value或者urlPattern
LoadOnStartUp=int值servlet对象什么时候加载
initParams为了携带信息,里面需要另外一个注解{@webInitParam(name=””,value=””)},{…}d