JAVA进阶

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:方法类型

  1. 类名.class
  2. 对象.getClass
  3. 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 &lt; 18 &amp;&amp; age &gt; 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 &lt; 18 &amp;&amp; age &gt; 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(, );
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值