JAVA
DAY01 单例多态
定义类的格式:
修饰符class类名{
1.成员变量(Field:描述类和对象的属性信息的)
2.成员方法(Method:描述类或者对象的行为信息的)
3.构造器(Constructor:初始化一个类的对象并返回引用)
4.代码块
5.内部类
} 只要不是这五大成分放在类下就会报错
构造器格式
修饰符 类名(形参){
}
构造器初始化对象格式:类名 对象名 = new 构造器;
this关键字
this代表了当前对象的引用。
this关键字可以用在实例方法和构造器中。
用在方法中,谁调用这个方法,就代表谁。
用在构造器中,代表了构造器正在初始化的那个对象的引用。
封装
面向对象三个特征:封装、继承、多态
封装作用:
1.提高安全性
2.实现代码的组件化
封装规范:
1.成员变量都私有:用private修饰。
2.提供成套的getter+setter方法暴露成员变量的取值和赋值。
3.合理隐藏,合理暴露。
static关键字
通过static关键字区分成员变量属于类还是属于对象的。
有static修饰的变量也叫类变量属于类本身
有static修饰的方法也叫类方法属于类本身
成员变量访问语法:
静态成员变量访问:类名.静态成员变量
实例成员变量访问:对象.实例成员变量
成员方法访问语法:
静态方法访问:类名.静态方法
实例方法访问:对象.实例方法
public class Demo01 {
public static String SchoolName="四川大学";
private String name;
private int age;
private String sex;
public Demo01(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
public String getSex() {return sex;}
public void setSex(String sex) {this.sex = sex;}
public static void inAddr(){
System.out.println("我在四川大学学习。");
}
public void getStudent(){
System.out.println(name+"已经"+age+"岁了");
}
public static void main(String[] args) {
System.out.println(Demo01.SchoolName);
inAddr();
Demo01.inAddr();
Demo01 s=new Demo01("yhh", 22, "男");
s.getStudent();
}
}
成员变量内存访问机制(方法类似)
继承(extends)
一般到特殊的关系,是一种子类到父类的关系,
可以提高代码的复用
特点:子类继承一个父类,子类可以直接得到父类的属性(成员变量)和行为(方法)。
子类 extends 父类 {}
方法重写
@Override
重写后调用父类方法需要中转
super:父类引用
继承后构造器的特点
子类构造器的第一行默认先访问父类的无参数构造器,在执行子类自己的构造器
子类构造器第一行super();默认存在
子类构造器中可以通过super根据参数调用对应父类构造器
this(…)和super(…)在构造器中使用必须在第一行
继承特点
1.单继承:一个类只能继承一个直接父类(可能出现代码二义性)
2.多层继承:一个类可以间接继承多个父类
3.一个类可以有多个子类
4.一个类要么默认继承Object类,要么间接继承了Object类
引用数据类型(作为参数类型和返回值)
public void go(student a){
a.run();
}
class student{
public void run(){
System.out.println("yhh");
}
}
作为成员变量
引用类型作为成员变量(复合类型)
抽象类(abstract )
概述
公共父类(类似声明)子类必须实现所有抽象方法
抽象方法——表达概念无法实现具体代码的方法
抽象类——表达概念而无法构造出实体的类
抽象类的使用及意义
为了被子类继承
体现模板思想,部分实现,部分抽象
一个类继承了抽象类,必须重写全部抽象方法
抽象类特征
获得了拥有抽象方法的能力
失去了创建对象的能力(抽象方法不能执行)
其他类的特征都拥有
抽象类的模板模式
优秀软件设计架构和思想,后来者可以使用这些架构或者思想设计出优秀、提高效率、提高软件可扩展性和可维护性的软件。
作用:优化代码架构、提高代码复用。
接口(interface)
体现规范思想,实现接口的子类必须写完接口的全部抽象方法(接口是彻底的抽象)
接口中抽象方法可以省略关键字(public abstract),常量(public static final)变量值只有一个,程序运行的过程中无法修改
接口实现
实现类——接口(接口被类实现)
接口与接口多继承
类实现接口的格式:
修饰符 class 实现类名称 implements 接口1,接口2,接口3,…{
}
class pingpongMan implements SportMan,Exit{
@Override
public void run() {
}
@Override
public void competition() {
}
@Override
public void rule() {
}
@Override
public void abroad() {
}
@Override
public void exit() {
}
}
interface SportMan extends Law,Go{
void run();
void competition();
}
interface Law{
void rule();
}
interface Go{
void abroad();
}
interface Exit{
void exit();
}
接口新增三个方法:
默认方法(default:由实现接口类对象调用)静态方法(static:只能由实现类名调用)私有方法(private:给私有和默认方法调用)
接口的使用
实现多个接口中同名的静态方法不会冲突
子类继承一个父类又实现多个接口时,成员方法与默认方法重名,子类优先执行父类的成员方法
一个类实现多个接口时,接口中存在同名的默认方法时必须重写这个方法
接口:可以多实现
抽象类:只能被一个类继承
代码块
静态代码块
格式:static{}
必须用static修饰,属于类,会与类一起优先加载,而且自动触发执行一次。
可以用于执行类的方法之前进行静态资源的初始化操作。
实例代码块
格式:{}
必须无static修饰,属于类的每个对象,会与类的每个对象一起加载,每次创建对象的时候自动触发执行一次。
作用:初始化实例资源
实例代码块提到构造器中执行的
final关键字
final可以用于修饰类、方法、变量
(1)final修饰类:类不能被继承
(2)final修饰方法:方法不能被重写
(3)final修饰变量:变量有且只能被赋值一次
abstract和final的关系?互斥关系,不能同时出现。
final修饰局部变量
让值被保护起来,执行的过程中防止被修改。
final修饰静态成员变量
变量变成常量(常量一般公开)
final修饰实例变量
!!!单例设计模式(重点)
单例:一个类永远只存在一个对象,不能创建多个对象
单例实现方式(8种):目前两种饿汉、懒汉
饿汉单例
通过类获取单例对象时,对象已经提前创建好
实现步骤:1.定义一个单例类
2.把类的构造器私有
3.定义一个静态成员变量用于存储一个对象
4.定义一个方法返回单例对象
public class SingleInstanceDemo01 {
public static SingleInstanceDemo01 ins=new SingleInstanceDemo01();//在此处调用构造器创建对象
private SingleInstanceDemo01(){
}
public static SingleInstanceDemo01 getInstance(){
return ins;
}
public static void main(String[] args) {
SingleInstanceDemo01 s1=SingleInstanceDemo01.getInstance();
SingleInstanceDemo01 s2=SingleInstanceDemo01.getInstance();
System.out.println(s1==s2);
}
}
懒汉单例(延迟加载)
通过类获取单例对象的时候发现没有对象才去创建一个对象
实现步骤:1.定义一个单例类
2.把类的构造器私有
3.定义一个静态成员变量用于存储一个对象
4.定义一个方法返回单例对象,判断对象不存在才创建一次,对象存在则直接返回
public class SingleInstanceDemo02 {
public static SingleInstanceDemo02 ins;
private SingleInstanceDemo02(){
}
public static SingleInstanceDemo02 getInstance(){
if(ins==null){
ins=new SingleInstanceDemo02();
}
return ins;
}
public static void main(String[] args) {
}
}
枚举类
用于做信息标志和信息分类
格式:
修饰符 enum 枚举名称{
实例1名称,实例2名称,…
}
enum Oritation{
UP,DOWN,LEFT,RIGHT
}
public class EnumDemo {
public static void main(String[] args) {
move(Oritation.UP);
}
public static void move(Oritation oritation){
switch (oritation){
case UP:
System.out.println("上");
break;
case DOWN:
System.out.println("下");
break;
case LEFT:
System.out.println("左");
break;
case RIGHT:
System.out.println("右");
break;
}
}
}
枚举类特点
!!!多态
多态概述
多态的形式:
父类类型 对象名称 =new 子类构造器;
父类类型范围>子类类型范围
接口 对象名称 = new 实现类构造器;
同一个类型的对象,执行同一个行为,在不同状态下表现出不同的行为特征
对于方法的调用:编译看左边,运行看右边
对于变量的调用;编译看左边,运行看左边
多态的使用前提
1.必须存在继承或者实现关系
2.必须存在父类类型的变量引用子类类型的对象
3.需要存在方法重写
多态的优势
1.在多态的形式下,右边对象可以实现组件化切换,业务能力也随之改变,便于扩展和维护。
2.在实际开发过程中,父类类型作为方法形式参数,传递给子类对象方法,可以传入一切子类对象进行方法的调用。
多态劣势
在多态形式下,不能调用子类独有功能。
引用类型的类型转换
引用类型的自动类型转换(小范围对象赋值给大范围的变量)
引用类型的强制类型转换(大范围对象赋值给小范围的变量)
可以解决多态劣势
强制类型转换可能出现类型转换异常问题
if (A instanceof Cat){
Cat c1=(Cat) A;
}
项目示例
public class PolymorphicDemo {
public static void main(String[] args) {
Computer c=new Computer();
USB xiaomi=new Mouse("小米");
c.installUSB(xiaomi);
USB lg=new KeyBoard("罗技");
c.installUSB(lg);
}
}
class Computer{
public void installUSB(USB usb){
//usb可能是鼠标或者键盘
usb.connect();
if(usb instanceof Mouse){
Mouse m=(Mouse) usb;
m.DoubleClick();
}else if (usb instanceof KeyBoard){
KeyBoard k=(KeyBoard) usb;
k.keyDown();
}
usb.unconnect();
}
}
class Mouse implements USB{
private String name;
Mouse(String name) {
this.name = name;
}
public void DoubleClick(){
System.out.println("双击");
}
@Override
public void connect() {
System.out.println(name+"成功接入了设备");
}
@Override
public void unconnect() {
System.out.println(name+"成功拔出了设备");
}
}
class KeyBoard implements USB{
private String name;
KeyBoard(String name) {
this.name = name;
}
public void keyDown(){
System.out.println(name+"写下了");
}
@Override
public void connect() {
System.out.println(name+"成功接入了设备");
}
@Override
public void unconnect() {
System.out.println(name+"成功拔出了设备");
}
}
//定义USB规范,必须完成接入和拔出
interface USB{
void connect();
void unconnect();
}
!!!内部类
概述
定义在一个类内部
可以提供更好的封装性,内部类具有更多权限修饰符,封装性具有更多的控制
静态内部类
static修饰,属于外部类本身,只会加载一次
**访问:**外部类名称.内部类名称
**创建:**外部类名称.内部类名称 对象名称=new 外部类名称.内部类构造器;
实例内部类(成员内部类)
无static修饰,属于外部类的对象
**访问:**外部类名称.内部类名称
**创建:**外部类名称.内部类名称 对象名称=new 外部类构造器.new 内部类构造器;
局部内部类
定义在方法中,构造器中,代码块中,for循环中的内部类
只能定义实例成员和常量
匿名内部类
概述
目的:简化代码
格式:
new 类名|抽象类|接口(形参){
方法重写
};
特点:1.没有名字的内部类
2.一旦写出来就立即创建一个匿名内部类的对象返回
3.匿名内部类的对象类型相当于是当前new的那个类型的子类型
匿名类的使用形式
开发常见形式
public class Anonymity {
public static void main(String[] args) {
Swim yhh= () -> System.out.println("yhh is swimming good!");
go(yhh);
go(new Swim() {
@Override
public void swimming() {
System.out.println("yhh is swimming good!");
}
});
}
public static void go(Swim s){
System.out.println("start");
s.swimming();
System.out.println("end");
}
}
interface Swim{
void swimming();
}
包
命名规范:
公司域名的倒写+技术名称(全部使用英文)
相同包下的类可以直接访问,不同包下的类需要导包才能使用
权限修饰符
DAY02 正则泛型集合
Object类
public String toString()
1.直接调用返回对象在内存中的地址
2.开发中直接输出对象变量的地址信息是无意义的,因此需要重写toString()
equals()
1.默认比较两个对象的地址是否相同
2.比较内容是否相同
重写步骤:
1.判断类型
2.判断内容是否相同
Objects.equals(Object a, Object b)
!!!Date类
1.创建一个日期对象代表了系统此刻日期时间
2.时间毫秒值,可以用作为时间的计算
3.有参构造器.时间毫秒值转换为时间对象
DateFormat(SimpleDateFormat)类
format格式化时间
Date d=new Date();
System.out.println(d);
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");
String rs =sdf.format(d);
System.out.println(rs);
format格式化时间毫秒值
字符串时间转换成日期对象
1.定义字符串时间
2.把字符串时间解析成Date日期对象(创建一个SimpleDateFormat类对象
利用parse()
)
3.得到日期对象时间毫秒值
4.把时间毫秒值格式化为喜欢的字符串时间格式
String date="2022-04-09 10:10:30";
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date1=sdf.parse(date);
long time=date1.getTime()+(24L*60*60+15*60*60+30*60+29)*1000;
System.out.println(sdf.format(time));
Calendar
// 单例方式获取日历对象
Calendar rigjtNow= Calendar.getInstance();
// 日历获取年份等等
int year=rigjtNow.get(Calendar.YEAR);
// 日历修改年份
rigjtNow.set(Calendar.YEAR, 2023);
// 日历获取日期对象
Date d=rigjtNow.getTime();
// 日历获取时间毫秒值
long time=rigjtNow.getTimeInMillis();
// 701天后是那个日期
rigjtNow.add(Calendar.DAY_OF_YEAR, 701);
Math类
Math.abs(-10);//绝对值
Math.ceil(4.1);//向上取整
Math.floor(4.9);//向下取整
Math.pow(2, 3);//指数次方
Math.round(4.5);//四舍五入
System类
System.exit(0);//0表示正常终止
long time =System.currentTimeMillis();//得到当前时间毫秒值
SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(sdf.format(time));
System.arraycopy();//数组拷贝
BigDecimal类(包装浮点数成为大数据对象)
double a=0.1;
BigDecimal a1=BigDecimal.valueOf(a);
包装类
自动装箱、自动拆箱
包装类可以存储null
把字符串类型的数值转换成对应的基本数据类型的值
String str="23";
int numInt=Integer.valueOf(str);
!!!正则表达式
正则表达式做校验
任何字符
\d 数字: [0-9]
\D非数字:[^0- 9]
\s空白字符: [ \t\n\xOB\f\r]
\S非空白字符: [^\5]
\w单词字符: [a-zA-z_ 0-9]
\W非单词字符: [^\W]
Greedy数量词
X? X, 一次或一次也没有
X* X, 零次或多次
X+ X, 一次或多次
X{n}X, 恰好n次
X{n,}X,至少n次
X{n,m}X,至少n次,但是不超过m次
校验邮箱
public static boolean checKEmailRegex(String qq){
return qq!=null&&qq.matches("\\w{1,}@\\w{2,10}(\\.\\w{2,10}){1,2}");
}
可以与方法结合
//分割
String name="yhh,zhy,lbw";
String[] nameArrs=name.split(",");
//替换
String name="yhh,zhy,lbw";
System.out.println(name.replaceAll(",+", "/"));
正则表达式爬取信息
1.定义爬取规则
2.把正则表达式进行编译成为一个匹配规则对象
3.通过匹配规则对象得到一个匹配数据内容的匹配器对象
4.通过匹配器去内容中爬取出信息
String name="yhh,zhy,lbw";
String regex="\\w{3,10}";
Pattern pattern=Pattern.compile(regex);
Matcher matcher=pattern.matcher(name);
while (matcher.find()){
System.out.println(matcher.group());
}
!!!泛型
泛型没有继承关系
泛型就是一个标签:<数据类型>
ArrayList<String> lists=new ArrayList<>();
泛型:约束了操作的数据类型,从而不会出现类型转换异常
自定义泛型类与方法
类:修饰符 class 类名 <数据类型>{}
方法:修饰符 <泛型变量> 返回值类型 方法名称(形参列表){}
泛型做通用技术架构
泛型接口
修饰符 interface 接口名称 <泛型变量>{}
public interface Data<T>{
void add(T name);
void delete(T name);
void update(T name);
int query(T id);
}
通配符?
?可以在使用泛型的时候代表一切类型
泛型的上下限(?必须是子类或者其父类)
!!!Collection集合(接口)
集合是一个大小可变的容器
数组:类型和长度定义时被确定
Collection
Collection集合的遍历方式
1.迭代器
Iterator<String> it =lists.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
2.foreach循环(增强for)
for (String s:lists){
System.out.println(s);
}
3.Lambda表达式
lists.forEach(s-> System.out.println(s));
lists.forEach(System.out::println);
常见数据结构
栈
先进后出,后进先出。手枪弹夹
队列(queue)
先进先出,后进后出。各种排队叫号系统
线性表(数组)
元素存在索引(查询快、增删慢)
链表
不是连续存储区域(数据域、地址域)
查询慢、增删快
树
二叉树排序树(查找树)
可能出现瘸子现象
平衡二叉树
不要让树过高(左右子树高度差绝对值不能超过1)
旋转算法:提高结点
红黑树
就是平衡的二叉查找树
List集合(接口)
ArrayList集合
底层基于数组
遍历方式四种
ArrayList<String> lists=new ArrayList<>();
//在某个索引位置插入元素
lists.add(2,"MySQL");
System.out.println(lists);
//根据索引删除元素,并返回该元素
System.out.println(lists.remove(2));
//根据索引获取元素
System.out.println(lists.get(2));
//修改索引位置处元素
lists.set(1, "java3");
LinkedList集合
底层基于链表
//创建队列
LinkedList<String> queue=new LinkedList<>();
//入队
queue.addLast("1");
queue.addLast("2");
System.out.println(queue);
//出队
System.out.println(queue.removeFirst());
System.out.println(queue);
//做一个栈
LinkedList<String> stack=new LinkedList<>();
//压栈
stack.push("1");
stack.push("2");
stack.push("3");
System.out.println(stack);
//弹栈
System.out.println(stack.pop());
System.out.println(stack);
set集合(接口)
HashSet
//经典代码,无序的
Set<String> sets=new HashSet<>();
无序的原因
如果认为内容重复就重复了,那么必须重写hashCode和equals
LinkedHashSet
有序不重复,额外添加了链来维护添加顺序
TreeSet
默认大小升序排列不重复
自排序方式:
1.有值自动排序
2.首字符编号
3.引用数据类型(1.引用类型定义Comparable 2.为集合定义比较器Comparable )
private static void sortCards(List<Card> cards) {
Collections.sort(cards, new Comparator<Card>() {
@Override
public int compare(Card o1, Card o2) {
return o1.getIndex()-o2.getIndex();
}
});
}
//-----------------------------------------------------
private static void sortCards(List<Card> cards) {
Collections.sort(cards, (o1, o2) -> o1.getIndex()-o2.getIndex());
}
//------------------------------------------------------
private static void sortCards(List<Card> cards) {
Collections.sort(cards, Comparator.comparingInt(Card::getIndex));
}
!!!Collections工具类
用来操作集合的工具类
Collections.addAll(apples, a1,a2,a3);
Collections.sort(apples);
Collections.shuffle(apples);
可变参数
本质上是一个数组
只能有一个,且必须放最后面
sum();
sum(10);
sum(10,20,30,40);
sum(new int[] {10,20,30,40});
public static void sum(int... nums){
}
DAY03 Map异常线程死锁
!!!Map集合(键值对集合)
Map集合(双列集合,一个元素两个值元素格式,key=value)
都可以存入自定义数据类型
List<String> names=new ArrayList<>();//有序可重复,有索引
names.add();
names.size();
names.get();
Set<String> names=new HashSet<>();//无序不重复,无索引
names.add();
names.size();
Map<String,String> names=new HashMap<>();//无序不重复,无索引
Map集合特点
Map集合的完整元素{key1=value1,key2=value2,……}
Map集合适合做购物车这样的系统(键值对数据)
与Set集合底层一致
特点:
1.无序,不重复,无索引
2.重复键对应元素会覆盖前面整个元素
3.对于值无要求
HashMap:无序不重复,无索引
LinkedHashMap:无序可重复,无索引
Map的API
Map<String,String> names=new HashMap<>();//无序不重复,无索引
//添加元素
names.put("娃娃", "123");
//清空集合
// names.clear();
//判断是否为空
names.isEmpty();
//根据键获取值
names.get("娃娃");
//根据键删除整个元素
names.remove("yijia");
//是否包含某个键或值
names.containsKey("娃娃");
names.containsValue("123");
//获取全部键Set或者值Collection的集合
Set<String> keys=names.keySet();
Collection<String> values=names.values();
//集合的大小
names.size();
//合并其他Map集合
Map<String,String> maps1=new HashMap<>();
maps1.put("yh", "12");
names.putAll(maps1);
Map遍历方式
键找值
先获取键的集合Set在通过遍历键找值
键值对
将键值对作为一个整体遍历,但键值对没有直接数据类型
//获取键值对集合
Set<Map.Entry<String, String>> entries = names.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry);
}
此时键值对作为一个实体类型
Lambda表达式
names.forEach((k,v)-> System.out.println(k+"=>"+v));
LinkedHashMap
有序不重复
LinkedHashSet基于LinkedHashMap去掉值
TreeMap
有排序不重复
TreeSet基于TreeMap去掉值
Map实例
package test02;
import java.util.*;
/**
* @Author yehonghan
* @2022/4/10 13:38
*/
public class BookSystem {
//定义一个集合用于图书馆储存书本信息
public static final Map<String, List<Book>> BOOK_STORE = new HashMap<>();
public static final Scanner SYS_SCANNER=new Scanner(System.in);
//
public static void main(String[] args) {
//展示操作界面
showCommand();
}
private static void showCommand() {
System.out.println("===================欢迎进入系统==================");
System.out.println("=============(1)查看全部书籍 query==============");
System.out.println("=============(2)添加书籍信息 add================");
System.out.println("=============(3)删除书籍信息 delete=============");
System.out.println("=============(4)修改书籍信息 update=============");
System.out.println("==============(5)退出系统 exit==================");
System.out.print("请您输入您的操作:");
String command=SYS_SCANNER.nextLine();
//判断命令
switch (command){
case "query":
queryBooks();
break;
case "add":
AddBook();
break;
case "delete":
deleteBooks();
break;
case "update":
updateBooks();
break;
case "exit":
System.out.println("退出成功!!!");
System.exit(0);
break;
default:
System.err.println("您输入的命令无效,请重新输入:");
}
showCommand();
}
private static void updateBooks() {
queryBooks();
System.out.println("===========开始修改书本信息============");
while(true){
System.out.println("请输入修改书本栏目:");
String type=SYS_SCANNER.nextLine();
if(BOOK_STORE.containsKey(type)){
while (true){
System.out.println("请输入修改书本名称:");
String name=SYS_SCANNER.nextLine();
Book book=getBookByTypeAndName(type,name);
if(book==null){
System.err.println("您输入的书名不存在,请重新确认!");
}else {
System.out.println("请您输入添加书本名称:");
String newname=SYS_SCANNER.nextLine();
System.out.println("请您输入添加书本价格:");
String newprice=SYS_SCANNER.nextLine();
System.out.println("请您输入添加书本作者:");
String newauthor=SYS_SCANNER.nextLine();
book.setName(newname);
book.setPrice(Double.valueOf(newprice));
book.setAuthor(newauthor);
return;
}
}
}else {
System.out.println("您输入的栏目不存在,请重新确认!");
}
}
}
private static Book getBookByTypeAndName(String type,String name){
List<Book> books=BOOK_STORE.get(type);
for (Book book : books) {
if(book.getName().equals(name)){
return book;
}
}
return null;
}
private static void deleteBooks() {
if(BOOK_STORE.size()==0){
System.out.println("您的图书馆一本书都没有,请快去买书吧!");
}else {
queryBooks();
while (true){
System.out.println("请输入您要删除的书籍类型");
String type=SYS_SCANNER.nextLine();
if(BOOK_STORE.containsKey(type)){
while (true){
System.out.println("请输入删除书籍名称:");
String name=SYS_SCANNER.nextLine();
Book book=getBookByTypeAndName(type, name);
if (book==null){
System.out.println("没有该书籍名称,是否退出y?");
String ch=SYS_SCANNER.nextLine();
if(ch.equals("y")){
return;
}
}else {
List<Book> books=BOOK_STORE.get(type);
// book.setName("");
// book.setPrice(Double.valueOf(""));
// book.setAuthor("");
books.remove(book);
System.out.println("删除成功!");
return;
}
}
}else {
System.out.println("没有该书籍类型,是否退出y?");
String ch=SYS_SCANNER.nextLine();
if(ch.equals("y")){
return;
}else {}
}
}
}
}
private static void queryBooks() {
if(BOOK_STORE.size()==0){
System.out.println("您的图书馆一本书都没有,请快去买书吧!");
}else{
System.out.println("===========查看所有书籍====================");
System.out.println("类型\t\t\t\t\t书名\t\t\t\t\t 价格\t\t\t作者");
BOOK_STORE.forEach((type,books)->{
System.out.println(type);
for (Book book : books) {
System.out.println("\t\t\t\t\t"+book.getName()+"\t\t\t\t"+book.getPrice()+"\t\t\t"+book.getAuthor());
}
});
}
}
private static void AddBook() {
System.out.println("==========开始添加书籍===========");
System.out.println("请您输入添加书本栏目:");
String type=SYS_SCANNER.nextLine();
List<Book> books;
//判断是否存在栏目
if(BOOK_STORE.containsKey(type)){
//存在该栏目
books=BOOK_STORE.get(type);
}else{
books=new ArrayList<>();
BOOK_STORE.put(type, books);
}
System.out.println("请您输入添加书本名称:");
String name=SYS_SCANNER.nextLine();
double PriceDouble;
while (true){
try {
System.out.println("请您输入添加书本价格:");
String price=SYS_SCANNER.nextLine();
PriceDouble= Double.valueOf(price);
break;
}catch (Exception e){
System.err.println("输入的价格不对!");
}
}
System.out.println("请您输入添加书本作者:");
String author=SYS_SCANNER.nextLine();
Book book=new Book(name,PriceDouble, author);
books.add(book);
System.out.println("您添加在"+type+"下的书本"+book.getName()+"成功!");
}
}
冒泡排序(选择最大往后移动)
for(int i=0;i<arr.length-1;i++){
for (int j = 0; j < arr.length-i-1; j++) {
if(arr[j]>arr[j+1]){
int temp;
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
选择排序(选择最小往前移动)
for(int i=0;i<arr.length-1;i++){
for (int j = i+1; j < arr.length; j++) {
int temp;
if(arr[i]>arr[j]){
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
二分查找
public static int BinarySerach(int[] nums,int number){
int left=0;
int right=nums.length-1;
int mid=(left+right)/2;
while (left!=right){
if(nums[mid]>number){
right=mid-1;
}else {
left=mid+1;
}
mid=(left+right)/2;
if (number==nums[mid]){
return mid;
}
}
return -1;
}
!!!异常
异常:编译或者执行过程中出现的问题
java中异常继承的类是Throwable
Error Exception(异常,需要研究和处理)
编译时异常,运行时异常
常见运行时异常
//数组索引越界
int[] nums={2};
System.out.println(nums[1]);
//空指针异常
String name=null;
System.out.println(name.length());
//类型转换异常
Object o="齐天大神";
Integer s=(Integer) o;
//迭代器遍历没有此元素
//数学操作异常
int c=10/0;
//数字转换异常
String num="23aa";
Integer it=Integer.valueOf(num);
编译时异常
提醒程序员可能会出错,编译时必须处理
异常的默认处理机制
出现异常,创建异常对象,返回异常信息给调用者,JVM打印异常栈信息,关闭程序
编译时异常处理机制
1.抛出异常:
与默认异常类似
方法 throws 异常1,异常2{}
方法 throws Exception{}
2.捕获处理:
try{
}catch(Exception e){
e.printStackTrace();
有异常做什么处理}
3.异常一层层抛出最外层集中处理
运行时异常处理机制
应该避免,捕获异常即可
Finally
最终一定要执行,可以在代码执行完毕后进行资源的释放
自定义异常
需要继承异常接口Exception,并重写构造器,在使用出抛出
class OpenException extends Throwable{ }
class CloseException extends OpenException{ }
public class TryCatchTest {
public static int open(){
return -1;
}
public static void readFile() throws OpenException {
if(open()==-1){
throw new CloseException();
}
}
public static void main(String[] args) {
try {
readFile();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (OpenException e) {
e.printStackTrace();
System.out.println("close");
}
}
}
异常的作用
可以处理代码问题,防止程序出现异常后死亡
提高程序健壮性和安全性
!!!多线程(重点:并发编程)
线程是属于进程中的一个独立运行单元,一个进程可以包含多个线程,这就是多线程。
线程创建开销相对于进程来说比较小,线程也支持并发。
如何创建线程
方法一:Thread
1.定义一个类
继承线程类Thread,重写run方法,创建线程对象并调用start方法启动
。
优点:编码简单
缺点:无法继承其他类,功能单一
方法二:Runnable
2.定义一个线程任务类实现Runnable接口,重写run方法,创建线程任务对象,再把线程任务对象包装成线程对象,调用start方法启动。
优点:实现接口,可以继承其他类,功能可以增强,同一个线程任务对象可以被包装成多个线程对象
实现解耦任务代码与线程独立
缺点:复杂一点
public class ThreadDemo02 {
public static void main(String[] args) {
//创建任务对象
Runnable target=new MyRunnable();
//包装成线程对象
Thread t1=new Thread(target,"1号线程");
t1.start();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"==》"+i);
}
}
}
//-----------------------------------------------
//匿名内部类写法
new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "==》" + i);
}
}).start();public class ThreadDemo02 {
public static void main(String[] args) {
new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "==》" + i);
}
}).start();
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "==》" + i);
}
}
}
方法三:Callable
3.实现Callable接口
前面所有优点
public class ThreadDemo02 {
public static void main(String[] args) {
//创建call对象
Callable<String> call=new MyCallable();
//保存成任务对象
FutureTask<String> task=new FutureTask<>(call);
//包装成线程对象
Thread t=new Thread(task);
t.start();
for (int i = 0; i < 11; i++) {
System.out.println(Thread.currentThread().getName()+"=>"+i);
}
try {
String rs=task.get();
System.out.println(rs);
}catch (Exception e){
e.printStackTrace();
}
}
}
class MyCallable implements Callable<String>{
@Override
public String call() throws Exception {
int sum=0;
for (int i = 0; i < 11; i++) {
System.out.println(Thread.currentThread().getName()+"=>"+i);
sum+=i;
}
return Thread.currentThread().getName()+"执行结果是:"+sum;
}
}
线程API
t1.setName("1号线程");//可以通过有参构造器取名
t1.getName();
Thread.currentThread();//返回当前运行的线程
Thread.sleep(1000);//当前线程停止一秒
线程安全问题
多个线程同时操作一个共享资源的时候可能出现线程安全问题:比如同时修改或删除等操作
线程同步
同步代码块
可能出现问题代码上锁,每次只能一个线程进入,执行完毕自动解锁。
synchronized (锁唯一对象){
//核心代码
}
同步方法
方法名上加入synchronized
lock显示锁
//创建一个lock对象
private final Lock lock=new ReentrantLock();
String name = Thread.currentThread().getName();
lock.lock();
try {
if (this.money >= i) {
System.out.println(name + "来取钱,取出" + i);
this.money -= i;
System.out.println(name + "来取钱后,剩余" + this.money);
} else {
System.out.println(name + "来取钱,余额不足。");
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
线程通信
核心方法与实例DAY03_test05
lock.wait();//让当前线程进入等待状态
lock.notify();//唤醒锁对象上的某个线程
lock.notifyAll();//唤醒锁对象上的所有线程
线程状态(重点)
新建(new)线程对象没有线程特征
就绪和运行(t.start)
终止(Teminated)
锁阻塞(Blocked)
无限等待(Waiting)
计时等待(Timed Waiting)
!!!线程池
线程池是容纳多个线程的容器,其中线程可以反复使用
1.减低资源消耗
2.提高相应速度
3.提高线程可管理性
创建线程池
//1定义任务类----------------------------------
class MyRunable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"==>"+i);
}
}
}
//2创建线程池
ExecutorService pools= Executors.newFixedThreadPool(3);
//3创建任务
Runnable t=new MyRunable();
//4将任务交给线程池
pools.submit(t);
//5关闭线程池--------------------------------------
pools.shutdown();
//Callable创建线程池
public class ThreadPoolsDemo {
public static void main(String[] args) {
ExecutorService pools= Executors.newFixedThreadPool(3);
Callable t1=new MyCallable(10);
Callable t2=new MyCallable(15);
Callable t3=new MyCallable(20);
Future<String> f1=pools.submit(t1);
Future<String> f2=pools.submit(t2);
Future<String> f3=pools.submit(t3);
try {
String rs1=f1.get();
String rs2=f2.get();
String rs3=f3.get();
System.out.println(rs1);
System.out.println(rs2);
System.out.println(rs3);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable<String> {
private int n;
public MyCallable(int n){
this.n=n;
}
@Override
public String call() throws Exception {
int sum=0;
for (int i = 0; i < n; i++) {
sum+=i;
}
return Thread.currentThread().getName()+"==>"+sum;
}
}
!!!死锁
1.互斥使用
2.不可抢占
3.请求和保持
4.循环等待
new Thread(new Runnable(){
@Override
public void run() {
}
}).start();
Volatile解决并发不可见
//多个线程访问共享变量后,一个线程修改变量后,其他线程不可见
//JMM模型Java内存模型为多线程服务
//共享变量在主内存中,线程运行时拷贝到线程的工作内存中
//每个线程拥有工作内存
//加锁会清空工作内存
1.加锁synchronized
2.Volatile只能修饰实例变量和类变量(只是保证数据可见性)
private volatile boolean flag=false;//更改后通知其他工作内存变量失效
//Volatile只能保证线程可见性不能保存原子性
//加锁可以保证原子性
Atomiclnteger原子型
//创建原子对象
private AtomicInteger atomicInteger=new AtomicInteger();
//CAS(先比较再交换)读写
乐观锁悲观锁
CAS(乐观锁) Atomiclnteger
synchronized(悲观锁)
!!!并发包
ConcurrentHashMap
java官方提供的了性能优异且线程安全的并发包
HashMap在高并发情况下不安全
HashTable(全部加锁)线程安全,但性能较差已经淘汰
可以使用ConcurrentHashMap(局部加锁)线程安全且综合性能好CAS
long time=System.currentTimeMillis();
CountDownLatch
用于监督控制线程流转
public class CountDownLatchDemo {
public static void main(String[] args) {
CountDownLatch c=new CountDownLatch(1);//计数可以完成多步唤醒机制
new ThreadA(c).start();
new ThreadB(c).start();
}
}
class ThreadA extends Thread{
private CountDownLatch c;
public ThreadA(CountDownLatch c) {
this.c=c;
}
@Override
public void run() {
super.run();
System.out.println("A");
try {
c.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("C");
}
}
class ThreadB extends Thread{
private CountDownLatch c;
public ThreadB(CountDownLatch c) {
this.c=c;
}
@Override
public void run() {
super.run();
System.out.println("B");
c.countDown();
}
}
CyclicBarrier
循环屏障对象保证其他线程完成后触发一次线程任务
用于多个线程进行操作,最后汇总
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier c=new CyclicBarrier(5,new meeting());
for (int i = 0; i <5; i++) {
new EmployeeThread("员工"+i,c).start();
}
}
}
class meeting implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始组织会议!");
}
}
class EmployeeThread extends Thread{
private CyclicBarrier c;
public EmployeeThread(String s, CyclicBarrier c) {
super(s);
this.c=c;
}
@Override
public void run() {
super.run();
try {
System.out.println(Thread.currentThread().getName()+"正在进入会议室");
Thread.sleep(3000);
c.await();
}catch (Exception e){
e.printStackTrace();
}
}
}
Semaphore
控制线程的并发数量(相当于锁多个,先到先执行)
public class SemaphoreDemo {
public static void main(String[] args) {
MySemaphor mySemaphor=new MySemaphor();
for (int i = 0; i < 5; i++) {
Thread a=new MyThread(mySemaphor);
a.setName("线程"+i);
a.start();
}
}
}
class MySemaphor {
private Semaphore semaphore=new Semaphore(1);
public void login(){
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"进入时间="+System.currentTimeMillis());
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"登录成功!");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"离开时间"+System.currentTimeMillis());
semaphore.release();
}
}
class MyThread extends Thread{
private MySemaphor mySemaphor;
public MyThread(MySemaphor mySemaphor) {
this.mySemaphor=mySemaphor;
}
@Override
public void run() {
super.run();
mySemaphor.login();
}
}
Exchanger
用于线程间协作的工具类用于线程之间数据交流
public class ExchangerDemo {
public static void main(String[] args) {
Exchanger<String> exchanger=new Exchanger<>();
new Boy(exchanger).start();
new Girl(exchanger).start();
}
}
class Boy extends Thread{
private Exchanger<String> exchanger;
public Boy(Exchanger<String> exchanger) {
this.exchanger=exchanger;
}
@Override
public void run() {
super.run();
System.out.println("男孩送了锁");
try {
String rs=exchanger.exchange("锁");
System.out.println("男孩收到礼物"+rs);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Girl extends Thread{
private Exchanger<String> exchanger;
public Girl(Exchanger<String> exchanger) {
this.exchanger=exchanger;
}
@Override
public void run() {
super.run();
System.out.println("女孩准备了钥匙");
try {
String rs=exchanger.exchange("钥匙");
System.out.println("女孩收到礼物"+rs);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
DAY04 文件流Socket
Lambda表达式
简化匿名内部类的代码写法
格式:
(匿名内部类被重写方法的形参列表)->{
被重写方法的具体代码
(如果代码只有一行1.省略大括号和分号 2.return需要省略 3.参数类型可以不写 4.如果只有一个参数,括号可以省略 )
};
//简化Runable
Thread t=new Thread(()-> System.out.println(Thread.currentThread().getName()+"执行"));
//简化Comparator
Collections.sort(list,new Comparator<Student>(){
@Override
public int compare(Student s1, Student s2) {
return s1.getAge()- s2.getAge();
}
});
public class LambdaDemo {
public static void main(String[] args) {
Thread t=new Thread(()->System.out.println(Thread.currentThread().getName() + "执行"));
t.start();
List<Student> list=new ArrayList<>();
Student s1=new Student("yhh", 18, '男');
Student s2=new Student("yh", 19, '男');
Student s3=new Student("y", 20, '男');
Collections.addAll(list, s1,s2,s3);
Collections.sort(list,(Student o1, Student o2) -> s1.getAge()- s2.getAge());
}
}
class Student{
private String name;
private int age;
private char sex;
public Student(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
public char getSex() {return sex;}
public void setSex(char sex) {this.sex = sex;}
}
只能简化接口中只有一个抽象方法的匿名内部类写法
方法引用
进一步简化Lambda表达式
关键语法::
// lists.forEach(s-> System.out.println(s));
// lists.forEach(System.out::println);
静态方法引用
前后参数一样可以使用静态方法引用
// Collections.sort(list,( o1, o2) -> s1.getAge()- s2.getAge());
// Collections.sort(list,Student::CompareByAge);
public static int CompareByAge(Student o1,Student o2){
return o1.getAge()-o2.getAge();
}
实例方法引用
// lists.forEach(s-> System.out.println(s));
// lists.forEach(System.out::println);
特定类型引用
特定类型::方法
Arrays.sort(list,new Comparator<String>(){
@Override
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(s2);
}
});
//--------------------------------
Arrays.sort(list,String::compareToIgnoreCase);
构造器引用
//构造器引用
//格式:类名::new
s->new Student
Student::new
!!!Stream
用于解决集合和数组的API弊端
List<String> list=new ArrayList<>();
list.add("张三丰");
list.add("张三");
list.add("李三丰");
list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(System.out::println);
//获取stream流
Stream<String> str=list.stream();
Stream<Map.Entry<String,Integer>> map=map.entrySet().stream();
Stream<String> arrs1=Stream.of(arrs);
如何使用Stream
forEach //foreach遍历
count //统计个数
filter //过滤元素
limit //取前几个元素
skip //跳过前几个
map //加工方法 把原来元素加工然后重新放上去
concat //合并流
收集stream流
将stream流转回集合数组
Stream<String> list1=list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3);
List<String> list2=list1.collect(Collectors.toList());
System.out.println(list2);
!!!File
代表操作系统的文件对象
是用来操作操作系统的文件对象的,删除、获取、创建文件。
使用正斜杠/
使用反斜杠\
使用分隔符API:File.separator
创建文件对象:
使用绝对路径
:无法跨平台
**相对路径:**寻找过程目录下文件
File获取
f.getAbsolutePath();
f.getPath();
f.getName();
f.length();
//获取文件最后修改时间
long time=f.lastModified();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(time));
File判断
f.exists();
f.isFile();
f.isDirectory();
File创建和删除
f.createNewFile();
f.delete();
f.mkdir();
f.mkdirs();
File目录的遍历
f.list();
File[] files=f.listFiles();//获取一级文件目录下文件对象
递归搜索文件
递归三要素
1.递归终结点;
2.递归公式;
3.递归方向
public class RecursionDemo {
public static void main(String[] args) {
SearchFile(new File("D:/study"), "j1.png");
}
public static void SearchFile(File dir, String fileName){
//判断是否是文件夹
if(dir.exists()&&dir.isDirectory()){
//提取当前目录下的全部一级文件对象
File[] files=dir.listFiles();
//是否为空目录
if(files!=null&&files.length>0){
//遍历一级文件对象
for (File file : files) {
if(file.isFile()){
//是文件判断名称
if(file.getName().contains(fileName)){
System.out.println(file.getAbsolutePath());
//启动exe文件
Runtime r=Runtime.getRuntime();
try {
r.exec(file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
}else{
//是文件夹递归调用
SearchFile(file, fileName);
}
}
}
}
}
}
!!!IO流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter (实现类,低级流)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter (实现类,缓冲流)
InputStreamReader OutputStreamWriter 实现类转换流)
ObjectInputStream ObjectOutputStream (实现类,序列化流)
PrintStream PrintWriter (实现类,打印流)
字节输入输出流
字节输入流FileInputStream
按照字节读取文件数据到内存,性能极差
//按照一个字节读
InputStream inputStream=new FileInputStream(file);
int code1=inputStream.read();
System.out.println((char)code1);
//使用循环读
int ch;
while ((ch=inputStream.read())!=-1){
System.out.println((char) ch);
}
//按照字节数组读取
InputStream inputStream=new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt");
byte[] buffer=new byte[3];
//读取字节放入数组中返回读取字节数量
int len=inputStream.read(buffer);
System.out.println(len);
//读了多少倒出多少
String rs=new String(buffer,0,len);
System.out.println(rs);
//使用循环读
//读取字节放入数组中返回读取字节数量
int len;
while ((len=inputStream.read(buffer))!=-1){
String rs=new String(buffer,0,len);
System.out.println(rs);
}
//一次读所有字节
File file=new File("C:\\Users\\86152\\Desktop\\1.txt");
InputStream inputStream=new FileInputStream(file);
file.length();
byte[] buffer=new byte[(int) file.length()];
//读入字节进入数组并返回读入长度
int len=inputStream.read(buffer);
System.out.println(len);
String rs=new String(buffer,0,len);
System.out.println(rs);
//现有API
byte[] buffer=inputStream.readAllBytes();
String rs=new String(buffer,0,len);
System.out.println(rs);
字节输出流FileOutputStream
默认是数据覆盖管道
OutputStream outputStream=new FileOutputStream("C:\\Users\\86152\\Desktop\\2.txt");
outputStream.write(97);
outputStream.write('b');
//添加换行方法
outputStream.write("\r\n".getBytes(StandardCharsets.UTF_8));
byte[] bytes="java是真的很牛!".getBytes(StandardCharsets.UTF_8);
outputStream.write(bytes,0,7);
outputStream.flush();
outputStream.close();
//--------------------------------------------------------------------追加数据管道
OutputStream outputStream=new FileOutputStream("C:\\Users\\86152\\Desktop\\2.txt",true);
字节流做文件复制
InputStream inputStream=new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt");
OutputStream outputStream=new FileOutputStream("C:\\Users\\86152\\Desktop\\2.txt");
byte[] buffer=new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
outputStream.write(buffer,0,len);
}
System.out.println("复制完成!");
inputStream.close();
outputStream.close();
回收资源新方式
try (
InputStream inputStream=new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt");
OutputStream outputStream=new FileOutputStream("C:\\Users\\86152\\Desktop\\2.txt",true)
){
byte[] buffer=new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
outputStream.write(buffer,0,len);
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
字符输入输出流
字符输入流FileReader
//单个字符读取
Reader reader=new FileReader("C:\\Users\\86152\\Desktop\\1.txt");
int code=reader.read();
System.out.println((char)code);
//循环读取
int ch;
while ((ch=reader.read())!=-1){
System.out.println((char)ch);
//数组读
char[] chars=new char[1024];
//读入字符进入数组并返回读入长度
int len;
while ((len=reader.read(chars))!=-1){
String rs=new String(chars,0,len);
System.out.println(rs);
字符输出流FileWriter
Writer writer=new FileWriter("C:\\Users\\86152\\Desktop\\2.txt");
writer.write("叶宏汉");//可以写字符串
writer.write("加油!".toCharArray());//可以写字符数组
//-------------------------------------------------------------------复制文件
try(
Reader reader=new FileReader("C:\\Users\\86152\\Desktop\\1.txt");
Writer writer=new FileWriter("C:\\Users\\86152\\Desktop\\2.txt",true)
) {
char[] chars=new char[1024];
//读入字符进入数组并返回读入长度
int len;
while ((len=reader.read(chars))!=-1){
String rs=new String(chars,0,len);
writer.write(rs.toCharArray());
System.out.println("复制成功!");
}
} catch (Exception e) {
e.printStackTrace();
}
字节缓冲流
字节缓冲输入流BufferedInputStream
将低级流传入,包装成缓冲流
性能好的原因:先将磁盘文件加载到内存中缓冲池
try (
BufferedInputStream bufferedInputStream=new BufferedInputStream(
new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt"))
){
int len;
byte[] bytes=new byte[1024];
while ((len=bufferedInputStream.read(bytes))!=-1){
String rs=new String(bytes,0,len);
System.out.println(rs);
}
} catch (Exception e) {
e.printStackTrace();
}
字节缓冲输出流BufferedOutputStream
数据直接输出到缓冲池
字符缓冲流
字符缓冲输入流BufferedReader (强烈建议使用)
数据直接输入到缓冲池
可以按行读入
public class BufferedStreamDemo {
public static void main(String[] args) {
try (
BufferedReader bufferedReader=new BufferedReader(new FileReader("C:\\Users\\86152\\Desktop\\1.txt"))
){
int len;
char[] bytes=new char[1024];
while (-1 != (len = bufferedReader.read(bytes))){
String rs=new String(bytes,0,len);
System.out.println(rs);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//----------------------------------经典代码------------许多业务需求需要按行读----------------------------------------
try (
BufferedReader bufferedReader=new BufferedReader(new FileReader("C:\\Users\\86152\\Desktop\\1.txt"))
){
String line;
while (null!=(line=bufferedReader.readLine())){
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
字符缓冲输出流BufferedWriter (强烈建议使用)
数据直接输出到缓冲池
public class BufferedStreamDemo {
public static void main(String[] args) {
try (
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter("C:\\Users\\86152\\Desktop\\1.txt",true))
){
bufferedWriter.write("yhh");
bufferedWriter.newLine();
bufferedWriter.write("yh");
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符转换流
解决读取不同编码文件读取乱码问题
字符输入转换流InputStreamReader
BufferedReader bufferedReader1=
new BufferedReader(//字符缓冲输入流
new InputStreamReader(//字符转换输入流
new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt"),"utf-8"));//字节缓冲输入流
字符输出转换流OutputStreamWriter
BufferedWriter bufferedWriter=
new BufferedWriter(//字符缓冲输出流
new OutputStreamWriter(//字符转换输出流
new FileOutputStream("C:\\Users\\86152\\Desktop\\1.txt"),"utf-8"));//字节缓冲输出流
!!!对象序列化
对象需要序列化必须实现接口Serializable
transient 修饰变量不参与序列化
序列化版本号:序列化和反序列化版本号必须一致
对象序列化:把java对象直接储存到文件中
对象反序列化:把java对象的文件数据恢复到java对象中
字节序列化输出流ObjectOutputStream
ObjectOutputStream objectOutputStream=
new ObjectOutputStream(
new FileOutputStream("C:\\Users\\86152\\Desktop\\2.txt"));
objectOutputStream.writeObject(user);
字节反序列化输入流ObjectInputStream
ObjectInputStream objectInputStream=
new ObjectInputStream(
new FileInputStream("C:\\Users\\86152\\Desktop\\2.txt"));
User user1=(User) objectInputStream.readObject();
System.out.println(user1);
!!!打印流PrintStream PrintWriter
PrintStream printStream=new PrintStream(new FileOutputStream("C:\\Users\\86152\\Desktop\\1.txt"));
//可以直接通向文件但必须覆盖
System.setOut(printStream);//让系统输出流向打印流,直接进入文件
属性集对象Properties
实际上是一个Map集合代表一个属性文件
properties.setProperty("admin", "123456");//保存一对属性
properties.getProperty("admin");//利用键获取属性值
Set<String> set=properties.stringPropertyNames();//获取键名称的集合
properties.store(outputStream, "备注");//保存数据到文件中
properties.load(inputStream);//从文件中读入
//写入属性集文件
public class PropertiesDemo {
public static void main(String[] args) throws Exception {
Properties properties=new Properties();
properties.setProperty("admin", "123456");
System.out.println(properties);
OutputStream outputStream=new FileOutputStream("C:\\Users\\86152\\Desktop\\1.txt");
properties.store(outputStream, "备注");
outputStream.close();
}
}
//读入属性集文件
public class PropertiesDemo {
public static void main(String[] args) throws Exception {
Properties properties=new Properties();
InputStream inputStream=new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt");
properties.load(inputStream);
System.out.println(properties);
inputStream.close();
}
}
啤酒问题和复制文件夹
public class BeerDemo {
public static void main(String[] args) {
BuyBeer(10);
System.out.println(BeerDemo.totalNum);
}
private static int totalNum;
private static int lastPingZiNum;
private static int lastGaiZiNum;
public static void BuyBeer(int money){
//拿钱买酒
int number=money/2;
//酒的数量
totalNum=totalNum+number;
//当前瓶子与盖子数量
int currentPingZiNum=lastPingZiNum+number;
int currentGaiZiNum=lastGaiZiNum+number;
//能换成多少钱
int totalMoney=0;
totalMoney = totalMoney + (currentGaiZiNum / 4) * 2;
lastGaiZiNum=currentGaiZiNum % 4;
totalMoney = totalMoney + (currentPingZiNum / 2) * 2;
lastPingZiNum=currentPingZiNum % 2;
if(totalMoney>=2) {
BuyBeer(totalMoney);
}
}
}
public class CopyDirDemo {
public static void main(String[] args) {
CopyDir(new File("C:\\Users\\86152\\Desktop\\2"),new File("C:\\Users\\86152\\Desktop\\1"));
}
public static void CopyDir(File srcDir,File destDir) {
if(srcDir.exists()&&srcDir.isDirectory()){
//创建目标文件夹
destDir.mkdirs();
//提取源文件夹一级对象
File[] files=srcDir.listFiles();
if(files!=null&&files.length>0){
for (File file : files) {
if (file.isFile()){
CopyFile(file,new File(destDir,file.getName()));
}
else{
CopyDir(file, new File(destDir,file.getName()));
}
}
}
}
}
private static void CopyFile(File srcfile, File destfile) {
try (
InputStream inputStream=new FileInputStream(srcfile);
OutputStream outputStream=new FileOutputStream(destfile)
){
byte[] buffer=new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
outputStream.write(buffer,0,len);
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
!!!Socket编程
C/S架构客户端服务端
B/S架构浏览器和服务器
InetAddress
InetAddress ip=InetAddress.getByName("www.yehonghan.top");
System.out.println(ip.getHostName());//获取域名
System.out.println(ip.getHostAddress());//获取地址
UDP通信
DatagramPacket 数据包对象用来封装要发送或者接受数据
DatagramSocket 用来发送或者接受数据包
public class UDPServerDemo {
public static void main(String[] args) throws Exception {
byte[] buffer=new byte[1024*64];
DatagramPacket datagramPacket=new DatagramPacket(buffer,buffer.length );
DatagramSocket datagramSocket=new DatagramSocket(6666);
datagramSocket.receive(datagramPacket);
String s=new String(buffer,0,datagramPacket.getLength());
System.out.println(s);
System.out.println(datagramPacket.getAddress().getHostAddress());//获取客户端ip
System.out.println(datagramPacket.getPort());//获取客户端端口
datagramSocket.close();
}
}
//----------------------------------------------------------------------------------
public class UDPClientDemo {
public static void main(String[] args) throws IOException {
byte[] buffer="今晚约吗?".getBytes(StandardCharsets.UTF_8);
DatagramPacket datagramPacket=new DatagramPacket(buffer,buffer.length , InetAddress.getLocalHost(),6666 );
DatagramSocket datagramSocket=new DatagramSocket();
datagramSocket.send(datagramPacket);
datagramSocket.close();
}
}
Socket
1.客户端要求请求与服务端Socket管道连接
2.从socket通信管道中得到一个字节输出流
3.通过字节输出流给服务端写数据
1.服务端ServerSocket注册端口
2.接受客户端的Socket管道连接
3.从socket中得到一个字节输入流,再读取信息
BIO 一对一 同步阻塞通信
public class ServerDemo {
public static void main(String[] args) throws Exception {
try (
ServerSocket socket=new ServerSocket(6666);
Socket listensocket=socket.accept();
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(listensocket.getInputStream()))
){
String msg;
if((msg=bufferedReader.readLine())!=null){
System.out.println(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//--------------------------------------------------------
public class ClientDemo {
public static void main(String[] args) {
try (
Socket clientsocket=new Socket("127.0.0.1",6666);
PrintStream printStream=new PrintStream(clientsocket.getOutputStream())
){
//请求连接
printStream.println("我是客户端");
printStream.flush();
System.out.println("发送完毕");
} catch (Exception e) {
e.printStackTrace();
}
}
}
NIO N对N 同步非阻塞
public class ClientDemo {
public static void main(String[] args) {
System.out.println("-----------客户端启动----------");
try (
Socket clientsocket=new Socket("127.0.0.1",6666);
PrintStream printStream=new PrintStream(clientsocket.getOutputStream())
){
while (true){
Scanner in=new Scanner(System.in);
//请求连接
System.out.println("请说:");
String msg=in.nextLine();
printStream.println(msg);
printStream.flush();
if(msg.equals("exit")){
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//-------------------------------------------------------------------------------------
public class ServerDemo {
public static void main(String[] args) throws Exception {
System.out.println("-------服务端启动--------");
try (
ServerSocket socket=new ServerSocket(6666)
){
while (true){
Socket listensocket=socket.accept();
new SocketDemo.MyServerReadThread(listensocket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//-----------------------------------------------------------------
public class MyServerReadThread extends Thread{
private Socket listensocket;
public MyServerReadThread(Socket listensocket) {
this.listensocket = listensocket;
}
@Override
public void run() {
super.run();
try {
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(listensocket.getInputStream()));
String msg;
while (((msg=bufferedReader.readLine())!=null)) {
System.out.println(msg);
if(msg.equals("exit")){
break;
}
}
} catch (IOException e) {
System.out.println("有人下线了!");
e.printStackTrace();
}
}
}
线程池
public class ServerExecutorDemo {
public static void main(String[] args) throws Exception {
System.out.println("-------服务端启动--------");
try (
ServerSocket socket=new ServerSocket(6666)
){
ThreadExecutor threadpools =new ThreadExecutor(3,100);
while (true){
Socket listensocket=socket.accept();
System.out.println("有人上线了");
//将任务交给线程池
threadpools.execute(new ReaderClientRunnable(listensocket));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//---------------------------------------------------------------------------
public class ReaderClientRunnable implements Runnable{
private Socket listensocket;
public ReaderClientRunnable(Socket listensocket) {
this.listensocket = listensocket;
}
@Override
public void run() {
try {
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(listensocket.getInputStream()));
String msg;
while (((msg=bufferedReader.readLine())!=null)) {
System.out.println(msg);
if(msg.equals("exit")){
break;
}
}
} catch (IOException e) {
System.out.println("有人下线了!");
}
}
}
//----------------------------------------------------------------------------
public class ThreadExecutor {
private ExecutorService executor;
public ThreadExecutor(int maxPoolSize,int queueSize) {
this.executor = new ThreadPoolExecutor(
//线程池初始线程数
maxPoolSize,
//线程池最多线程数
maxPoolSize,
//任务队列存活时间
120L,
//线程延时时间
TimeUnit.SECONDS,
//任务队列存放Runnable任务
new ArrayBlockingQueue<Runnable>(queueSize));
}
public void execute(Runnable task){
this.executor.execute(task);
}
}
//--------------------------------------------------------------------------------------
public class ClientExecutorDemo {
public static void main(String[] args) {
System.out.println("-----------客户端启动----------");
try (
Socket clientsocket=new Socket("127.0.0.1",6666);
PrintStream printStream=new PrintStream(clientsocket.getOutputStream())
){
while (true){
Scanner in=new Scanner(System.in);
//请求连接
System.out.println("请说:");
String msg=in.nextLine();
printStream.println(msg);
printStream.flush();
if(msg.equals("exit")){
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
B/S
public class BSserverDemo {
public static void main(String[] args) {
try (
ServerSocket serverSocket=new ServerSocket(8080)
){
while (true){
Socket socket=serverSocket.accept();
new ServerReaderThread(socket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ServerReaderThread extends Thread{
private Socket socket;
public ServerReaderThread(Socket socket) {
this.socket=socket;
}
@Override
public void run() {
super.run();
try {
PrintStream printStream=new PrintStream(socket.getOutputStream());
printStream.println("HTTP/1.1 200 OK");
printStream.println("Content-Type:text/html;charset=UTF-8");
printStream.println();
printStream.println("<h1>最牛逼的yhh</h1>");
Thread.sleep(10000);
printStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
图片上传
public class ClientDemo {
public static final String SRC_IMAGE="C:\\Users\\86152\\Desktop\\1\\1.jpg";
public static void main(String[] args) {
try (
Socket socket=new Socket("127.0.0.1",6666);
//获取文件进入字节缓冲输入流
BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(SRC_IMAGE))
){
OutputStream outputStream=socket.getOutputStream();
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(outputStream);
byte[] bytes=new byte[1024];
int len;
while ((len=bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);
}
bufferedOutputStream.flush();//刷新
socket.shutdownOutput();//通知服务端数据发送完毕
System.out.println("客户端传输图片完毕了!");
//接受相应数据
BufferedReader returnmsg=new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(returnmsg.readLine());
} catch (Exception e) {
e.printStackTrace();
}
}
}
//-------------------------------------------------------------------------------------
public class ServerDemo {
public static void main(String[] args) {
try (
ServerSocket listensocket=new ServerSocket(6666);
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(new FileOutputStream("C:\\Users\\86152\\Desktop\\2\\"+ UUID.randomUUID() +".jpg"))
){
Socket socket=listensocket.accept();
InputStream inputStream=socket.getInputStream();
BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream);
byte[] bytes=new byte[1024];
int len;
while ((len=bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);
}
bufferedOutputStream.flush();
PrintStream printStream=new PrintStream(socket.getOutputStream());
printStream.println("我已经收到你的文件!");
Thread.sleep(1000);
printStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
DAY05 反射
单元测试Junit
1.下载框架jar包
2.a模拟业务代码
b写测试类
c在测试类中写测试方法
d测试方法注意事项:必须public没有返回值宇参数、使用注解@Test
public class UserService {
public String login(String name, String password){
if ("admin".equals(name)&&"123456".equals(password)){
return "success";
}
return "用户名或者密码错误!";
}
}
public class UserServiceTest {
@Test
public void testLogin(){
UserService u=new UserService();
String rs= u.login("admin", "123456");
Assert.assertEquals("您的登录功能有错!","success",rs);
}
}
@before在测试实例方法前执行一次
@after在测试实例方法后执行一次
@BeforeClass在所有测试方法前执行一次
@AfterClass在所有测试方法后执行一次
!!!反射
反射、注解、代理、泛型
反射是指对于任何一个类,在“运行的时候”都可以得到这个类的全部成分。
得到编译后class文件对象
反射的作用
1.反射可以破坏面向对象的封装性,暴力反射
2.同时可以破坏泛型的约束性(泛型只能工作再编译阶段、运行阶段消失)
基于反射技术设计框架
//提供一个方法可以保存一切对象数据的字段
public static void save(Object obj) {
//解析对象的字段和每个字段的值储存起来
try (
PrintStream printStream=
new PrintStream(
new FileOutputStream("C:\\Users\\86152\\Desktop\\1\\1.txt",true))
){
Class c=obj.getClass();
printStream.println("========="+c.getSimpleName()+"============");
//定位它的全部成员变量
Field[] fields=c.getDeclaredFields();
for (Field field : fields) {
//字段名称
String name=field.getName();
//字段的值
field.setAccessible(true);//暴力破解不规范,应该调用get方法
String value=field.get(obj)+"";
printStream.println(name+"="+value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
获取class类对象
class:字节码文件类型
Constructor:构造器类型
Field:成员变量的类型
Method:方法类型
- 类名.class
- 对象.getClass
- Class.forName(“类的全限名”)
public static void main(String[] args) throws ClassNotFoundException {
//类名直接获取
Class c1=Student.class;
System.out.println(c1);
//对象获取
Student s=new Student();
Class c2 = s.getClass();
System.out.println(c2);
//直接加载
Class c3=Class.forName("ReflectionDemo.Student");
System.out.println(c3);
System.out.println(c1.getSimpleName());//获取类名本身
System.out.println(c1.getName());//获取全名
}
获取构造器对象
//获取public修饰的构造器
@Test
public void getConstructors(){
Class c=Student.class;
Constructor[] cons=c.getConstructors();
for (Constructor con : cons) {
System.out.println(con.getName()+"===>"+con.getParameterCount());
}
}
//无视权限获取全部构造器
@Test
public void getDeclaredConstructors(){
Class c=Student.class;
Constructor[] cons=c.getDeclaredConstructors();
for (Constructor con : cons) {
System.out.println(con.getName()+"===>"+con.getParameterCount());
}
}
//获取某个构造器
@Test
public void getConstructor() throws Exception {
Class c=Student.class;
//根据参数匹配只能拿public修饰的
Constructor con=c.getConstructor(String.class ,int.class);
System.out.println(con.getName()+"===>"+con.getParameterCount());
}
//无视权限获取按参数匹配
@Test
public void getDeclaredConstructor() throws Exception {
Class c=Student.class;
//根据参数匹配只能拿public修饰的
Constructor con=c.getDeclaredConstructor(String.class ,int.class);
System.out.println(con.getName()+"===>"+con.getParameterCount());
}
!!!获取构造器初始化对象
@Test
public void Createobj01() throws Exception{
//先得到class对象
Class c=Student.class;
//再获取无参构造器对象
Constructor constructor=c.getDeclaredConstructor();
//将private权限打开
constructor.setAccessible(true);
//通过无参构造器初始化对象返回
Student s=(Student)constructor.newInstance();
System.out.println(s);
s.setName("yhh");
s.setAge(12);
System.out.println(s.getName());
System.out.println(s.getAge());
}
@Test
public void Createobj02() throws Exception{
//先得到class对象
Class c=Student.class;
//再获取有参构造器对象
Constructor constructor=c.getDeclaredConstructor(String.class,int.class);
//通过有参构造器初始化对象返回
Student s=(Student)constructor.newInstance("yhh",12);
System.out.println(s);
System.out.println(s.getName());
System.out.println(s.getAge());
}
获取成员变量
@Test
public void getDeclaredFields(){
//获取全部成员变量
Class c=Student.class;
Field[] fields=c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName()+"==>"+field.getType());
}
}
@Test
public void getDeclaredField() throws Exception {
//获取某个成员变量
Class c=Student.class;
Field field=c.getDeclaredField("age");
System.out.println(field.getName()+"==>"+field.getType());
}
!!!为成员变量赋值
@Test
public void setField() throws Exception {
//获取类名
Class c=Student.class;
//获取成员变量
Field nameF=c.getDeclaredField("name");
//获取无参构造器
Constructor constructor=c.getDeclaredConstructor();
//无视private
constructor.setAccessible(true);
//创建一个对象
Student s=(Student)constructor.newInstance();
//无视private
nameF.setAccessible(true);
// Student s=new Student();
//
nameF.set(s, "yhh");
System.out.println(s);
String value=nameF.get(s)+"";
System.out.println(value);
}
!!!获取Method对象
@Test
public void getDeclaredMethods(){
//得到所有Method对象
Class c=Student.class;
Method[] methods=c.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName()+"==>"+method.getParameterCount()+"==>"+method.getReturnType());
}
}
@Test
public void getDeclaredMethod() throws Exception {
//得到所有对象
Class c=Student.class;
//定位toString方法利用方法名和参数
Method toString=c.getDeclaredMethod("toString");
System.out.println(toString.getName()+"==>"+toString.getParameterCount()+"==>"+toString.getReturnType());
Student student=new Student("yhh", 12);
//触发执行
//invoke(被触发方法对象,方法需要入参)
String value=(String)toString.invoke(student);
System.out.println(value);
}
注解
用在类上、方法上、成员变量、构造器上对成分进行编译约束,标记的,有标记就进行特殊处理
1.标记@interface Book{} 2.方法重写约束 3.函数式接口约束@FunctionalInterface
注解的属性
特殊属性String value(); 单独使用时可以省略value名称不写
public class AnnotationDemo {
@Book(name = "java",authors = {"yhh","yh"})
public static void main(String[] args) {
}
}
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Book{
String name();
String[] authors();
String address() default "china";
}
元注解
用来注解自定义注解
@Target()约束标记范围
@Retention()约束存活范围
注解解析
Annotation注解父类
AnnotatedElement
public class AnnotationDemo1 {
@Test
public void parseClass() {
//定义类对象
Class c=BookStore.class;
// Method method=c.getDeclaredMethod("run");
//判断这个类上是否使用了某个注解
if(c.isAnnotationPresent(Book.class)){
//获取注解对象
Book book=(Book) c.getDeclaredAnnotation(Book.class);
System.out.println(book.value());
System.out.println(book.price());
System.out.println(Arrays.toString(book.authors()));
}
}
}
@Book(value = "java",price = 99.5,authors = {"yhh","yh"})
class BookStore{
@Book(value = "c",price = 99.5,authors = {"yhh","yh"})
public void run(){
}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Book{
String value();
double price() default 100;
String[] authors();
}
注解使用
public class AnnotationDemo2 {
@MyTest
public void test01(){
System.out.println("======1=====");
}
public void test02(){
System.out.println("======2=====");
}
@MyTest
public void test03(){
System.out.println("======3=====");
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
AnnotationDemo2 annotationDemo2=new AnnotationDemo2();
Class c=AnnotationDemo2.class;
Method[] methods=c.getDeclaredMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(MyTest.class)){
method.invoke(annotationDemo2);
}
}
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyTest{
}
XML可扩展标记语言
数据交换(区分大小写)
用于系统配置文件
数据存储
组成成分
<?xml version="1.0" encoding="utf-8" ?>
<!-- 处理能力导入css一起做界面-->
<!--声明-->
<!--注释-->
<!--标签只能有一个根标签-->
<person>
<name id="1" desc="yhh">yhh</name>
<age>22</age>
<sql>
<!-- 实体字符不能写-->
select * from student where age < 18 && age > 12 ;
</sql>
<sql>
<!-- 字符数据区-->
<![CDATA[
select * from student where age < 18 && age > 12 ;
]]>
</sql>
</person>
约束技术
DTD规范技术不能验证数据类型
Schema可以约束数据类型
XML解析
DOM解析 面向对象解析
优点:生成DOM树可以随意访问修改删除 缺点:占内存较多
SAX解析 事件驱动解析
优点:读取一行解析一行并释放内存 缺点:使用过的元素不能访问,只能查找
工厂模式
1.对象通过工厂的方法创建和返回,可以为对象进行加工和数据注入
2.可以实现类与类之间的解耦
生产对象的方法,产生一个工厂类相当于中间分配结点
装饰模式
创建一个新类,包装原始类,从而在新类中提升原来类的功能
Commons-io包
简化io流读写数据
//完成文件复制
IOUtils.copy(new FileInputStream(), new FileOutputStream());
//完成文件复制到文件夹
FileUtils.copyFileToDirectory();
//复制文件夹到文件夹
FileUtils.copyDirectoryToDirectory();
//java1.7以后
Files.copy(, );
,标记的,有标记就进行特殊处理
1.标记@interface Book{} 2.方法重写约束 3.函数式接口约束@FunctionalInterface
注解的属性
特殊属性String value(); 单独使用时可以省略value名称不写
public class AnnotationDemo {
@Book(name = "java",authors = {"yhh","yh"})
public static void main(String[] args) {
}
}
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Book{
String name();
String[] authors();
String address() default "china";
}
元注解
用来注解自定义注解
@Target()约束标记范围
@Retention()约束存活范围
注解解析
Annotation注解父类
AnnotatedElement
public class AnnotationDemo1 {
@Test
public void parseClass() {
//定义类对象
Class c=BookStore.class;
// Method method=c.getDeclaredMethod("run");
//判断这个类上是否使用了某个注解
if(c.isAnnotationPresent(Book.class)){
//获取注解对象
Book book=(Book) c.getDeclaredAnnotation(Book.class);
System.out.println(book.value());
System.out.println(book.price());
System.out.println(Arrays.toString(book.authors()));
}
}
}
@Book(value = "java",price = 99.5,authors = {"yhh","yh"})
class BookStore{
@Book(value = "c",price = 99.5,authors = {"yhh","yh"})
public void run(){
}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Book{
String value();
double price() default 100;
String[] authors();
}
注解使用
public class AnnotationDemo2 {
@MyTest
public void test01(){
System.out.println("======1=====");
}
public void test02(){
System.out.println("======2=====");
}
@MyTest
public void test03(){
System.out.println("======3=====");
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
AnnotationDemo2 annotationDemo2=new AnnotationDemo2();
Class c=AnnotationDemo2.class;
Method[] methods=c.getDeclaredMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(MyTest.class)){
method.invoke(annotationDemo2);
}
}
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyTest{
}
XML可扩展标记语言
数据交换(区分大小写)
用于系统配置文件
数据存储
组成成分
<?xml version="1.0" encoding="utf-8" ?>
<!-- 处理能力导入css一起做界面-->
<!--声明-->
<!--注释-->
<!--标签只能有一个根标签-->
<person>
<name id="1" desc="yhh">yhh</name>
<age>22</age>
<sql>
<!-- 实体字符不能写-->
select * from student where age < 18 && age > 12 ;
</sql>
<sql>
<!-- 字符数据区-->
<![CDATA[
select * from student where age < 18 && age > 12 ;
]]>
</sql>
</person>
约束技术
DTD规范技术不能验证数据类型
Schema可以约束数据类型
XML解析
DOM解析 面向对象解析
优点:生成DOM树可以随意访问修改删除 缺点:占内存较多
SAX解析 事件驱动解析
优点:读取一行解析一行并释放内存 缺点:使用过的元素不能访问,只能查找
工厂模式
1.对象通过工厂的方法创建和返回,可以为对象进行加工和数据注入
2.可以实现类与类之间的解耦
生产对象的方法,产生一个工厂类相当于中间分配结点
装饰模式
创建一个新类,包装原始类,从而在新类中提升原来类的功能
Commons-io包
简化io流读写数据
//完成文件复制
IOUtils.copy(new FileInputStream(), new FileOutputStream());
//完成文件复制到文件夹
FileUtils.copyFileToDirectory();
//复制文件夹到文件夹
FileUtils.copyDirectoryToDirectory();
//java1.7以后
Files.copy(, );