JAVA基础

命名规范

项目名     全小写
    
包        全小写       域名反写:从大到小
    
类		 大驼峰命名:每个单词首字母大写,其他字母小写
    
方法       小驼峰命名
    
变量 		 小驼峰命名:第一个单词全小写,第二个开始每个单词首字母大写

image-20221116192710937

包和类的关系

类对应一个源代码,源文件     xxx.java  
    
包就是文件夹,就是对类进行分类管理
    
package声明包,必须在源代码的第一条语句。告诉系统当前类所在的包的位置
import导入包,当前类要使用其它类不在同一包,要告诉系统,要使用的类的包的所在位置
    不需要导入的情况
        同一个包的类
        java.lang包中类会自动导入

JDK JRE JVM的区别和联系

JDK

JDK是Java Development Kit的缩写,是Java的开发工具包。
包括了Java运行环境(JRE),Java工具(javac/java/jdb等)和Java基础的类库(即Java API )。  

JRE

JRE(Java Runtime Environment,Java运行环境),包含JVM标准实现及Java核心类库。 JRE是Java运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器),只是针对于使用Java程序的用户。

JVM

JVM(Java Virtual Mechinal),Java虚拟机,是JRE的一部分。它是整个java实现跨平台的最核心的部分,负责解释执行字节码文件,是可运行java字节码文件的虚拟计算机。

JDK=JRE+开发工具

JRE=JVM+类库(系统封装好的类,API)

JVM实现跨平台

环境变量的配置

环境变量
JAVA_HOME
        D:\develop\Java\jdk1.8.0_221
            
Path
         %JAVA_HOME%bin

idea 和eclipse的区别

eclipse 免费 一个窗口同时展示多个项目
idea 收费 一个窗口只能展示一个项目 一个项目下创建多个模块 功能强大 机器硬件要求高

数据类型和变量

基本数据类型
    byte(-128----+127) short int long  	---整型
    float double						---浮点型
    char								---字符型
    boolean								---布尔型
引用数据类型
    类    
        自定类
        JRE类库中的系统类    String Scanner
    数组
     
 
抽象        具体
数据类型    变量
类         对象
类就是对象的数据类型
对象就是类的一个实例
    
分析设计系统
    对象-----抽象-----类
编码
    定义类----创建对象
    
    
类型转换
    兼容数据类型
    隐式转换(自动转换)
        小的赋值给大的
        char byte short,参与运行,结果会自动为int
        要一个大的类型,参与,结果会转成这种类型
        char byte short---int---float---double
    显示转换(强制类型转换)
        大的赋值给小的
        问题:精度丢失
 //常量:字面值常量,整数默认都是int,小数默认都是double
//        double d=1.1;
//        float f=1.1F;
//        long i=1111111111111L;
        //字面值常量,int,没用超过类型的范围,可以赋值
        byte b1=127;
        //上面的规则对变量无效
        int i=127;
        byte b2=i;
    
标识符    
变量名
    命名规范
    语法规范
        数字,字母,_,$
        数字不能开头
        不能使用系统关键字和保留字
            关键字:这些单词用来构成程序的特殊语法结构
            保留字:候选关键字,Java底层C语言    goto和const    
    
    

向下转型

Aaa aaa =new Aaa;
Bbb bbb =new Bbb;
//a是父类对象,指向子类对象的地址
//假转型
aaa=bbb;
bbb=(Bbb)aaa;
//真转型  会报错,编译器可以运行,但运行时出错
bbb=(Bbb)aaa;


静态方法是属于类的

非静态方法

运算符

算术运算符    + -  * /  %        ++   --
赋值运算符    =    +=    
关系运算符    >   >=   !=   ==
逻辑运算符    &&     ||    !
三目运算符    条件? 值1:值2
优先级  ()最高

流程控制

三种
    顺序
    选择
    循环
   

选择结构

单分支
if(条件){
    代码块;
}
if()
    只有一条语句可以省略{}
二选一
if(条件){
    代码块1;
}else{
    代码块2;
}
多选一
if(条件1){
    代码块1;
}else if(条件2){
    代码块2;
}else if(条件3){
    代码块3;
}else if(条件4){
    代码块4;
}else{
    代码块5;
}
程序流程图
switch(变量/表达式){
    case 常量1:
        代码块1;
        break;        //编码case穿透
    case 常量2:
        代码块2;
        break;
    case 常量3:
        代码块4;
        break;
    defalut:
        代码块4;
        break;
}
switch-case缺点
    变量能够匹配的类型有限制
        JDK1.5之前    byte short char int 
        JDK1.5开始    枚举类型
        JDK1.7开始    String
    等值匹配,区间范围比较不灵活
switch-case优点
    执行性能比多重if块

循环

1.while(循环条件){
    循环体;
}

2.do{
    循环体;
}while(循环条件);


3.for(表达式1;表达式2;表达式3){
    循环体;
}
表达式1:循环变量初始值
表达式2:循环条件
表达式3:修改循环变量的值,使循环结束
break        结束整个循环
continue    结束本次循环

双重循环

类和对象

增删改都不需要返回值

查需要返回值

抽象类
抽象方法
final
多态
	使用步骤
        子类重写父类方法
        子类对象赋给父类
        父类调用方法执行的子类方法
    典型应用
    	父类类型做参数
    	父类类型做返回值	


访问修饰符

访问修饰符
				本类	同包  子类	其它
    private		 Y
    默认(不写)	  Y		Y
    protected	 Y	  Y     Y	
    public		 Y	  Y		Y	Y
    
    
单例:无论调用多少次创建对象的方法,内存中只分配一个对象
	饱汉/懒汉
	public class Singleton{
		private static Singleton singlton;
		
		private Singleton(){}
		
		public static Singleton getInstance(){
			if(singlton==null){
				singlton=new Singleton();
			}
			return singleton;
		}
	}
	
	饿汉
	public class Singleton{
		private static Singleton singlton=new Singleton();
		
		private Singleton(){}
		
		public static Singleton getInstance(){
			return singleton;
		}
	}
	
重载:同一个类,方法名相同,参数不同(参数个数,参数类型)
		
重写:子类,和父类的方法签名一般完全相同
	增强父类的功能
	
				访问修饰符	返回值类型					方法名		参数		抛出异常	
		重写	不能比父类更严格  父类返回值类型及其子类类型 	相同		相同			有要求		

抽象类

抽象
	对象---->类---->父类----->父类......----->抽象类
	
抽象类
	一般位于继承层级结构的上层节点,类似于一个骨架。定义所有子类公有的行为,这些行为的具体实现有子类自己完成,抽象类没有必要实现。
	定义类中使用abstract关键字

抽象方法只定义,不实现。
	声明方法使用abstract关键字,没有方法体{}
    public abstarct class 类名{
    	public abstract 返回值 方法名(参数列表);
    }
   
抽象方法所在的类必须是抽象类
抽象类中可以不定义抽象方法
子类继承抽象类,必须重写抽象类的抽象方法,除非这个类也是抽象类
抽象类不能实例化

Object

Object类是所有类的父类,为什么这个类的方法不是抽象方法
	自定义输出:重写toString()
	自定义相等的比较规则:重写equals()
	
如果是抽象方法,增加使用的麻烦

Java是单继承

面向对象是一种设计思想,不同的编程语言都支持
	C++ 	Java	C# 
C++支持多继承,一个类可以同时继承多个父类
Java、C#都是单继承, 一个类只能有一个直接父类


继承:
	子类共有的属性,封装到父类。子类继承父类的属性,也可以扩展自己的属性。
	父类可以定义子类共有的行为,父类可以实现,也可以不实现。子类可以直接使用,也可以重写,可以扩展父类没有的行为
	优点:
		节省代码,减少冗余。方便修改扩展
	缺点
		低耦合(依赖性),高内聚(独立性)
		继承是高耦合

final关键字

final:最终的,不变

修饰变量,就是常量

public static void main(String[] args) {
        int a=1;
        a=4;
        a=5;
        //可以修饰局部变量
        final int b=5;
        //赋值以后不能修改
        //b=6;
        System.out.println("b="+b);
    }
class Ddd{
    int a;
    //声明成变量必须赋值
    final int b=5;

    void test(){
        //不能修改
        //b=6;
        System.out.println(b);
    }
}
class Eee{
    //可以在构造方法中修改
    final  int b;

    public Eee(int b){
        this.b=b;
    }

    void test(){
        //error
        //b=6;
    }
}
class Fff{
    //最常见的用法,静态常量,一般都用大写。  MY_NAME_XXX
    public static final  int MAX=123;
}


public class Test03 {
    public static void main(String[] args) {
        System.out.println(Fff.MAX);
    }
}

image-20221122114216994

修饰方法,不能被重写

修饰类,不能被继承

String类能不能继承
	public final class String
    	implements java.io.Serializable, Comparable<String>, CharSequence {
    	
    	}

设计模式

设计模式,一类问题的一种解决方案。软件开发的经验总结。

单例:对象只创建一个
简单工厂
	一个父类	Car					抽象产品
	若干子类	Benz	BMW			实体产品
	工厂类		CarFactory			 实体工厂
工厂方法
抽象工厂

类型转换

向上转型,安全的
	父类对象=子类对象
向下转型,不安全
	真转型		运行异常
		子类对象=父类对象	
	假转型		安全的
		父类对象已经指向了子类对象
		子类对象=父类对象
		
instanceof
	对象 instanceof 类型

多态的优缺点

优点:代码灵活,方便扩展
	父类类型 对象=new 子类构造器();
	
缺点:
	不能通过父类类型调用子类的特有方法

重写equals()方法,实现自定义对象,自定义比较相对的规则

    //自定义两个学生对象的相等比较规则:所有属性值都相同,就是同一个学生
//    public boolean equals(Object obj) {
//        if(obj==null){
//            return false;
//        }
//        if(obj instanceof Student){
//            //如果比较的对象是学生,才按照学生的属性比较
//            //假转型
//            Student other= (Student) obj;
//            return this.id==other.id
//                    &&this.name.equals(other.name)
//                    &&this.age==other.age;
//        }
//        return false;
//    }


    @Override
    public boolean equals(Object o) {
        //地址相同,属性值相同
        if (this == o) return true;
        //参数为null,或者和当前对象不是同一个数据类型
        if (o == null || getClass() != o.getClass()) return false;
        //向下转型,假转型
        Student student = (Student) o;
        return id == student.id && age == student.age && Objects.equals(name, student.name);
    }

接口

接口是一种数据类型(抽象类型),是抽象方法的集合,接口使用interface关键字。
一个类通过继承接口的方式,从而来继承接口的抽象方法
类描述对象的属性和方法。接口则包含类要实现的方法。

接口是一组规范,主要是用来规范行为,功能,方法

接口中定义成员变量,默认就是public static final

接口中的方法只定义不实现(JDK1.8之前),定义方法可以不写访问修饰符,默认就是public

接口不能实例化,可也通过多态的使用方法,将接口的实现类对象,赋给接口的实例变量

一个类实现接口必须实现接口中的所有方法,除非这个类也是抽象类

Java是单继承,一个类只能有一个直接父类。一个类可也同时实现多个接口。父类在前,接口在后。
	public class 实现类 extends 父类 implements 接口1,接口2
	
---------------------------------------------------------------------------

接口是对单继承的一种扩展,接口间接实现了多继承。实现接口的耦合度比继承父类的耦合度小。

JDK1.8扩展了接口的功能:
	接口的方法可以实现,使用static或者default关键字。
	接口中的方法有默认实现,实现类实现接口的方法时可也按需选择实现重写,减少代码。

接口可也继承接口,可也继承多个。实现类似功能组合的作用。将几个基础的接口整合成一个功能更复杂的接口。
			定义						成员变量								
	抽象类		abstract class			访问修饰符任意,是否静态任意,是否常量任意	  		
	接口		interface				默认都是public static final		
    
    		方法
    抽象类	  访问修饰符任意,是否静态任意,有没有抽象方法任意	
	接口	   默认public 	JDK1.8之前不能写方法体	JDK1.8以后可以使用static和default关键字定义有方法体的方法			
	
	
	子类继承抽象类
	实现类实现接口

Comparable 语法

Comparable 语法
首先实现接口
public class Student implements Comparable
然后重写compareTO方法将
public int compareTo(Object o) {
        if (o instanceof Student){
            Student other=(Student) o;
            return this.age-other.age;
        }
        return 0;
    }
才能调用方法Arrays.sort(students);




comparator

先定义一个比较器,实现方法
    public class AgeDesc implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        return o2.getAge() - o1.getAge();
    }
}
调用方法 
    Arrays.sort(students,new AgeDesc());

匿名内部类

Comparator comparator=new Comparator<Student>() {
        @Override
        public int compare(Student o1, Student o2) {
            return o1.getAge()-o2.getAge();
        }
    };Arrays.sort(students);

匿名-例子

1创建另一个类来实现接口,通过另一个类来实现
      interface  Interface1{
        void aaa();

    }
    class  Class1{
        public void test(Interface1 interface1){
            interface1.aaa();
        }
    }
    class Class2 implements Interface1{

        @Override
        public void aaa() {
            System.out.println("实现匿名内部类");
        }
    }
public class MyInterface {
        public static void main(String[] args) {
            Class1 class1=new Class1();
            class1.test(new Class2());
        }
    }

如果不想创建类,实现接口,就使用匿名内部类
   
        interface  Interface1{
        void aaa();

    }
    class  Class1{
        public void test(Interface1 interface1){
            interface1.aaa();
        }
    }
public class MyInterface {
        public static void main(String[] args) {
            
            new Class1().test(new Interface1() {
                @Override
                public void aaa() {
                    System.out.println("实现匿名内部类");
                }
            });
        }
    }


两种比较器例子

1、使用两种比较器实现自定义对象数组的自然排序和自动规则排序

comparable

public class Student implements Comparable{
    private String name;
    private int id;
    private int age;

    public Student(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }

    public Student(){}

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Object o) {
        if (o instanceof Student){
            Student other=(Student) o;
            return this.age-other.age;
        }
        return 0;
    }
}
import java.util.Arrays;

public class Test1 {
    public static void main(String[] args) {
        Student[] students =new Student[3];
        students[0]=new Student("zs",1,18);
        students[1]=new Student("ls",2,12);
        students[2]=new Student("ww",3,14);
        System.out.println("排序前"+Arrays.toString(students));
        Arrays.sort(students);
        System.out.println("排序后"+Arrays.toString(students));

    }
}
comparator


import java.util.Comparator;

public class AgeDesc implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        return o2.getAge() - o1.getAge();
    }
}
public class Test1 {
    public static void main(String[] args) {
        Student[] students =new Student[3];
        students[0]=new Student("zs",1,18);
        students[1]=new Student("ls",2,12);
        students[2]=new Student("ww",3,14);
        System.out.println("排序前"+Arrays.toString(students));
        Arrays.sort(students,new AgeDesc());
        System.out.println("排序后"+Arrays.toString(students));

    }
}

2、Comparotor使用匿名内部类实现

import java.util.Arrays;
import java.util.Comparator;

public class Test1 {
    public static void main(String[] args) {
        Student[] students =new Student[3];
        students[0]=new Student("zs",1,18);
        students[1]=new Student("ls",2,12);
        students[2]=new Student("ww",3,14);
        System.out.println("排序前"+Arrays.toString(students));
    Comparator comparator=new Comparator<Student>() {
        @Override
        public int compare(Student o1, Student o2) {
            return o1.getAge()-o2.getAge();
        }
    };Arrays.sort(students);
        System.out.println("排序后"+Arrays.toString(students));

    }
}

3、主方法中添加代码,调用test()方法

interface Interface1{
void aaa();
}

class Class1{
public void test(Interface1 interface1){
interface1.aaa();
}
}

interface  Interface1{
    void aaa();

}
class  Class1{
    public void test(Interface1 interface1){
        interface1.aaa();
    }
}
public class MyInterface {
        public static void main(String[] args) {
            new Class1().test(new Interface1() {
                @Override
                public void aaa() {
                    System.out.println("实现匿名内部类");
                }
            });
        }
    }

4、输入一个字符串,统计数字,大写字母,小写字母各有多少个。

import java.util.Scanner;

public class TongJi {
    public static void main(String[] args) {

        Scanner scanner=new Scanner(System.in);
        System.out.println("输入一个字符串");
        String str = scanner.next();
        int up=0;
        int low=0;
        int num=0;
        for (int i = 0; i <str.length() ; i++) {
            char c=str.charAt(i);
            if (c>='A'&&c<='Z'){
                up++;
            }
            else  if (c>='a'&&c<'z'){
                low++;
            }else if (c>'0'&&c<'9'){
                num++;
            }
        }
        System.out.println("大写字母:"+up);
        System.out.println("小写字母:"+low);
        System.out.println("数字:"+num);

    }
}

5、字符串反转:输入abcefg,输出gfecba

public class FanZhuan {

    public static void main(String[] args) {
        String str="abcefg";
        for (int i =  str.length()-1; i>=0; i--) {
            System.out.print(str.charAt(i));

        }
    }
}

6、字符串查找子串”abcwonxiuydewonxiuyfghiwonxiuyjklmwonxiuyl”,统计”woniuxy”出现的次数

public class SearchSonString {

//    字符串查找子串"abcwonxiuydewonxiuyfghiwonxiuyjklmwonxiuyl",统计"woniuxy"出现的次数
    public static void main(String[] args) {
        String str="abcwonxiuydewonxiuyfghiwonxiuyjklmwonxiuyl";
        String[] strings=str.split("woniuxy");
        int count =strings.length-1;
        System.out.println("woniuxy出现的次数为:"+count);
    }
}

集合

Collection

Collection 单列集合 
     List 有顺序的,可重复的    顺序是添加顺序
    	ArrayList 底层是数组,可以进行下标操作(一般都是使用ArrayList集合)
    	Linkedlist 底层是双向链表
    	Vector		底层是数组
     10  后面是*1.5
    Set  不重复
    	HashSet 无序 hash表:数组+链表 
    				扩容: 16   后面是*0.75
    				去重: hashcode()equals(
    				根据hash值来确定顺序,所以无序
    	LinkedHashSet 有序  hash表保证不重复 链表保证有序
    	TreeSet  有序   红黑树
    			去重+排序 comparable +comparator
    			
    
    set都是map的

Map

Map 双列集合
    HashMap
    LinkedHashMap
    TreeMap

数组和链表的区别

数组 内存中分配的是一段连续的空间
    查询快:数组通过下标访问,只要知道首地址,就可以快速计算出任何一个元素的地址
    增删慢:增或删都要进行数组的扩容或缩容,操作起来比较麻烦。
链表  内存中不是连续的空间,每个节点会记录前一个和下一个元素的地址
    查询慢:
    增删快;

linkedList

Arraylist的方法都有,底层实现不同
    有专门操作头尾元素的方法
    getFirst()  getLast()
    addFirst() addLast()
    removeFirst() removeLast()

Vector

ArrayList 		  线程不安全,效率高
Vector    加了锁的,线程安全,效率低

HashSet

不重复:添加元素会自动去重判断
无序:添加的顺序和内存中的顺序不一致
   
HashSet底层
    hash表:元素是链表的数组,相同HashCode的对象,在同一个数组的下标位置,通过单向链表关联在一起的
 JDK1.7 数组+链表
 JDK1.8 数组+链表+红黑树

HashSet去重原理

hashCode()+equals()
    
hashCode()方法
    
Object:默认实现:根据对象的内存地址使用Hash散列算法,计算出来的一个整数
String类重写:安装字符串中每个字符的编码做了一个累加
自定义类:使用所有的属性值做一个*固定数累加
    
HashSet去重判断相等
    
     先判断hashCode()
        hashCode()不同,属性值一定不同,直接添加
        hashCode()相同,属性值可能相同,也可能不同
            判断equals()
                equals()相同,不添加
                equals()不相同,添加
      
自定义类型去重:重写equals()和hashCode()
     
     
扩容
    初始化没有指定长度,默认是0,第一添加,初始16个。加载因子0.75;
    实际数据容量到16*0.75=12,扩容,原来的2倍 32
    32*0.75=24    扩容,64
        
    树化:链表转成红黑数:容量>=64链表的长度>=8
        
    下标位置:
    二次hash

HashMap

HashSet就是HashMap的key
    
Map接口的实现类,每一个元素由两个部分组成。键值对:key-value
key必须唯一
通过key获取value
key和value可以是任意类型,都支持泛型
    
添加
    V put(K key, V value);

通过key获取Value值
    V get(Object key);

删除所有元素
    void clear();

通过key删除元素
    V remove(Object key);

是否存在指定的key
    boolean containsValue(Object value);

是否存在指定的value
    boolean containsValue(Object value);

获取所有key的集合,key不重复,所有定义成Set<K>    
    Set<K> keySet();

获取所有value的集合,value可以重复,所有定义成Collection<V>
    Collection<V> values();

//entrySet() entry的set集合
//Set<Map.Entry<Integer, Student>> set集合,集合中的元素是Map.Entry<Integer, Student>
//Map.Entry<Integer, Student>是一种数据类型    Map接口.Entry接口
//一个Entry就是一个键值对    
    Set<Map.Entry<K, V>> entrySet();

LinkedHashSet

Set 不重复 
    HashSet         不重复,无序
    LinkedHashSet    不重复,有序( 遍历的顺序和添加顺序一致)
    
LinkedHashSet:
    使用Hash表保证不重复    保证添加元素不重复:equals 和 hashCode
    使用链表保证有序

TreeSet

Set 不重复 
    HashSet         不重复,无序
    LinkedHashSet   不重复,有序
    TreeSet         不重复,有序,自定义排序
    
底层是红黑树
    
数据结构
    线性表
    图
    树   根节点  叶子节点
      二叉树
      平衡树:  左边分支的元素,比右边小,两边的层高最多差一层(所有数据查询,都是相同的查询效率)
      红黑树:   不是严格平衡树,在查询平均性能和添加删除效率上做了一个折中的设计
            根节点是黑色的
            叶子节点也是黑色的,都是null
            红色节点的子节点必须是黑色
            任何一个节点到叶子节点的所有路径中,经过的黑色节点的个数必须相同
          
https://www.cs.usfca.edu/~galles/visualization/RedBlack.html

 public TreeSet()            
     底层使用自然排序Comparable
     
 public TreeSet(Comparator<? super E> comparator)
      底层使用自定义排序Comparator
     
保证添加元素不重复:          
        comparable或comparator
        正数  >
        负数    <
        0     ==

LinkedHashMap

LinkedHashSet就是LinkedHashMap的key
LinkedHashMap:key不重复,有顺序

TreeMap

TreeSet就是TreeMap的key

数据持久化

我们前的集合和数组,数据都在内存中
数据持久化,我们要把数据永久保存,数据持久化存储到硬盘中:
    文件    
        读数据、写数据(I/O流)
        学习File    异常处理
    数据库    CRUD

File

一切皆对象
File    文件和目录路径(文件夹)名的抽象表示形式。 
    
Java    文件和文件夹封装成一个类
    
C#    File  Directory
    
构造器
    public File(String pathname)
    
创建目录
    public boolean mkdir()    上级目录必须存在
    
    public boolean mkdirs()    无论多少层目录会自动创建
    
创建文件
    public boolean createNewFile()

递归

方法自己调用自己,避免栈溢出
递归
    递推:将复杂的问题,往简单的情况退,推到最简单情况,可也得到一个已知值
    回归:再从这个已知值,往回算
如求1加5的值
递推:
sum(5)=sum(4)+5  15
sum(4)=sum(3)+4  10
sum(3)=sum(2)+3  6
sum(2)=sum(1)+2  3
sum(1)=1         1
                回归
斐波拉契数列        
1,1,2,3,5,8,13,21...
n>2 f(n)=f(n-1)+f(n-2)
n=1 n=2 f(n)=1
f(5)=f(4)+f(3)
f(4)=(f3)+f(2)
f(3)=f(2)+f(1)
f(2)=1
f(1)=1

BigInteger

解决整数运算超出范围
大整数运算

BigDecemal

解决小数运算的范围和精度问题
小数的精确计算

Date

JDK提供的一个日期时间类,JDK1.8以后新增了很多其它的
new Date()
new Date(时间毫秒)

DateFormat

public final String format(Date date)
    日期转字符串
public Date parse(String source) 
    字符串转日期

异常处理

语法错误:编译错误,不能运行
逻辑错误:正常运行,期望的结果和运行结果不同
    
异常:程序运行时出错
    
Throwable
    Error        错误,不需要程序员处理。Error一般是系统级别的问题。    
    Exception
                 异常,出现异常,程序必须处理,如果程序员不处理,虚拟机处理。虚拟机遇到异常,挂了,停止运行。
    
处理异常的基本结构
    try{
        //可以能会发生异常的代码
    }catch(异常类型 变量){
        //发生异常以后要执行的代码
    }finally{
        //有没有异常都会执行的代码,一般做资源的清理
    }

    一个try可以配多个catch,父类在后,子类在前
        
异常分类
    受查异常    checked exception
        编译异常
        编译检查代码中的异常有没有处理,没有处理,编译报错
        除了RuntimeException及其子类
    非受查异常
        运行异常
        编译时,不检查
        RuntimeException及其子类
        
throw 
    写在代码中
    throw 异常对象
    只有执行这句话一定会抛出异常
        
throws
    写在方法声明后面        方法名() throws 异常类{}
    是一种处理异常的语法:就是告诉编译器这方法可能有异常,要求调用方法的调用者来处理异常
        
方法重写(增强)
    最常见的形式:方法签名一致
    方法名        相同
    参数         相同
    访问修饰符   不能比父类更严格
    返回值      父类方法返回值的类型或者子类类型
    throws       子类重写父类方法不能抛出比父类更大的异常

I/O流

数据持久化:文件,数据库 
    
输入流
    读数据:文件的数据读入内存    
输出流
    写数据:内存的数据写入文件
        
字节流
    操作字节
    XxxxxInputStream    XxxxOutputStream
字符流
    操作字符
    XxxxReader    XxxxWriter

字节流

字节流是功能最强大的,可以读写任何文件。
其它的流,底层都是靠字节流的基本功能实现的。
操作字符麻烦。 
    
操作字节
XxxxxInputStream    XxxxOutputStream
    
OutputStream    抽象类
    FileOutputStream    
        public abstract void write(int b)        一次写一个字节
        public void write(byte b[])                一次写一个字节数组

InputStream        抽象类
    FileInputStream
        public  int read()                    一次读一个字节
         public int read(byte b[])            一次读一个字节数组

标准的异常处理

public static void main(String[] args) {
        OutputStream os=null;
        try {
            os=new FileOutputStream("z:\\a.txt");
            os.write("abcdef中文".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
public static void main(String[] args) {
        InputStream inputStream=null;
        try{
            inputStream=new FileInputStream("a.txt");
            byte[] bytes=new byte[1024];
            int length;
            while((length=inputStream.read(bytes))!=-1){
                System.out.println(new String(bytes,0,length));
            }
        }catch (IOException ex){
            ex.printStackTrace();
        }finally {
            if(inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

复制文件

一个流读取文件,一个流写入

带缓冲区的字节流

InputStream
    FileInputStream
    FilterInputStream
        BufferedInputStream
BufferedOutputStream
    
读写数据的时候,底层添加了一个数据缓冲区,读写性能块

字符流

字节流功能是最强的,操作中文不方便
    
字符流底层还是字节流
    
字符流底层就是:字节流+编码表
    
编码表:内存中的一串01编码和现实中一个字符的对应关系
    ASCII    一个字节    256中编号
    ISO-8859-1             拉丁编码
    GB2312/GBK/GB18030    简体中文
    BIG5                大五码,繁体中文
    Unicode                utf-8
    
乱码,编码和解码使用的码表不同
    编码:字符--->字节
    解码:字节--->字符
        
使用字符流,一次读取一个字符或者字符数组(字符串)
        
转换流
Writer
    OutputStreamWriter
Reader
    InputstreamReader
        
复制文件:
    字节流任何文件都可以
    记事本显示是乱码的文件,不能用字符流
        
转换流可以使用各种编码,我们在编程环境中一般还是使用默认编码
FileReader,FileWriter这两个流就是转换流的简化写法,不能更改编码,只能使用当前环境的默认编码。使用简单

带缓存区的字符流

BufferedReader
    public String readLine()    一次读取一行数据
BufferedWrite
    public void newLine()        换行,规避不同平台的底层指令不同的问题
换行输入:
    操作系统底层使用转义字符
        Windows        \r\n
        Unix Linux    \n
        Mac            \r

三层架构

/**
 * @author woniuxy
 * @date   2000-1-1
 * @version  1.1
 */
public class Test01 {
    
    static Scanner scanner=new Scanner(System.in);
    
    public static void main(String[] args) throws IOException {
        addStudent();
        getAllStudent();
    }
    
    private static void getAllStudent() throws IOException {
    }
    
    private static void addStudent() throws IOException {
    }
    
    /**
     * 查询所有学生信息
     * @return 学生集合
     */
    public static List<Student> selectAllStudents() throws IOException {
    }
    
    /**
     * 添加学生
     * @param student 学生对象
     * @throws IOException 异常
     */
    public static void insertStudent(Student student) throws IOException {
    }
}
UI:User Interface:用户的操作界面:和用户交互的一个界面:负责和用户交互,接受用户输入,展示结果
    main()
        程序入口
    getAllStudent()
        用户选择要执行的功能,显示查询的结构
    addStudent()
        用户选择要执行的功能,输入数据,执行添加操作
-------------------------------------------------------    
数据操作:执行数据的CRUD
    selectAllStudents()
        I/O操作查询文件
    insertStudent(Student student)
        I/O操作添加文件
单一职责:一个类功能是单一
    
分类
    UI类
    学生数据数据操作类
    学生类
    
处理学生数据还有别的数据:教师数据,班级数据,成绩数据,课程数据
     UI类
     学生数据数据操作类
     教师数据数据操作类
     班级数据数据操作类
     .....
     学生类
     教师类
     班级类
     .....
    
    
类都在一个包下,分包
    表示层:界面操作相关的类
    业务逻辑层:放业务逻辑处理(业务处理)
        业务操作:
            银行:存取,取钱,贷款,查询账号
            图书管:借书,还书,查询图书
            酒店:预定,入住,结账
    数据访问层:数据操作(学生数据操作)
                
    实体层(实体类):基础的数据类(学生):数据载体
                
                
命令规范
    实体层
        包    com.woniuxy.xxx.entity    
        类    Student    Teacher    Score
    数据访问层
        包    com.woniuxy.xxx.dao    
        接口    
            StudentDao    TeacherDao    ScoreDao
        实现类
            创建一个子包     com.woniuxy.xxx.dao.impl    
            类            StudentDaoImpl    TeacherDaoImpl    ScoreDaoImpl
   业务逻辑层
           包    com.woniuxy.xxx.service    
           接口    
            StudentService    TeacherService    ScoreService
        实现类
            创建一个子包     com.woniuxy.xxx.service.impl    
            类            StudentServiceImpl    TeacherServiceImpl ScoreServiceImpl
                
为什么要写接口
                
    没有接口
    Dao
        XxxDaoImpl    (文件实现)
        XxxDaoImplDb(数据库实现)        
    Service
        调用Dao    
            XxxDaoImpl xxxDao=new XxxDaoImpl();
            xxxDao.方法();

            XxxDaoImplDb xxxDao=new XxxDaoImplDb();
            xxxDao.方法();

    有接口
    Dao
        XxxDao 
            XxxDaoImpl    (文件实现)
            XxxDaoImplDb(数据库实现)  
        
    Service    可以使用多态
        调用Dao    
            XxxDao xxxDao=new XxxDaoImpl();
            xxxDao.方法();

            XxxDao xxxDao=new XxxDaoImplDb();
            xxxDao.方法();

命名规范

image-20221202154245226

Dao

image-20221202152055619

Service

image-20221202152919512

UI

image-20221202153312711

三层调用

image-20221202153604155

复习集合api

基础语法,逻辑流程
面向对象
	语法
	设计
API
	集合
		Collection
			List
				ArrayList
					数组	查询快,增删慢
					扩容:
				LinkedList
					链表	增删快,查询慢
				Vector
			Set
				HashSet
					hash表:数组+链表
					数组+链表+红黑数
					去重	hashCode() equals()
					扩容
				LinkedHashSet
					hash表保证不重复
					链表保证有序
				TreeSet
					红黑树
					去重+排序	Comparable Comparator
					
		Map
			HashMap
			LinkedHashMap
			TreeMap
	异常
		try{
		
		}catch(){
		
		}finally{
		
		}
		
		throws
		
		throw	代码块
	I/O

自定义异常

自定义异常

Exception
	RuntimeException
		NullPointerException
		IndexOutofBoundsException
		
        
        xxx1(){
        
        	if(){
        		throw new NullPointerException();
        	}
        }
        
        
		xxx2(){
        
        	if(){
        		throw new IndexOutofBoundsException();
        	}
        }
        
        
        xxx1(){
        
        	if(){
        		throw new RuntimeException("空指针");
        	}
        }
        
        
		xxx2(){
        
        	if(){
        		throw new RuntimeException(“数组下标越界”);
        	}
        }
        
        
异常就是一个名字,JDK定义的所有异常,就是名字不同,里面都是构造器

自定义异常就是根据自己的项目需要,自己给某种情况的异常指定一个自定义名。继承自Exception或者RuntimeException.

三层异常处理

Dao

public List<Student> selectAllStudents() {
        List<Student> students = new ArrayList<>();
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new FileReader("student.txt"));
            //读取文件,每一行数据,转换成学生对象,存入集合
            String line;
            while ((line = reader.readLine()) != null) {
                String[] strs = line.split("-");
                int id = Integer.parseInt(strs[0]);

                String name = strs[1];
                int age = Integer.parseInt(strs[2]);
                Student student = new Student(id, name, age);
                students.add(student);
            }
            return students;
        } catch (IOException e) {
            e.printStackTrace();
            throw new DaoException("Dao文件操作错误");
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

Service

public List<Student> getAllStudents()  {
        try {
            return studentDao.selectAllStudents();
        } catch (DaoException e) {
            e.printStackTrace();
            throw new ServiceException("业务处理错误,联系管理员,稍后重试");
        }
    }

UI

public static void getAllStudents() throws IOException {
        try{
            System.out.println(studentService.getAllStudents());
        }catch (ServiceException e){
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }

异常分类

Throwable 是所有异常的根
    Error 错误信息
    Exception 异常信息
    	CheckedException 受查异常 除了RuntimeException异常都是受查异常
    	RuntimeException 非受查异常

三层异常的操作流程

1.先自定义异常

如果是受查异常可以直接 throws 抛出

如果是非受查异常
在三层架构中
 1.自定义异常
    定义DaoException的异常,继承非受查异常,下面定义的是DaoException的构造器
    定义ServiceEXception异常继承非受查异常
 2.在Dao的实现类里面进行try catch的操作 在Dao里面catch捕获的是ioexception,throw  new DaoException
 3.在service里面进行try catch的操作 在catch里面捕获DaoException ,throw new ServiceEXception

1.DaoException异常自定义

package com.woniuxy.exception;
//自定义异常  类似于自己
public class DaoException extends RuntimeException{
    public DaoException() {
    }
    public DaoException(String message) {
        super(message);
    }

    public DaoException(String message, Throwable cause) {
        super(message, cause);
    }

    public DaoException(Throwable cause) {
        super(cause);
    }

    public DaoException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

2.ServiceEXception异常自定义

2.在Dao的实现类里面进行try catch的操作 在Dao里面catch捕获的是ioexception,throw new DaoException

package com.woniuxy.dao.impl;

import com.woniuxy.dao.StudentDao;
import com.woniuxy.entity.Student;
import com.woniuxy.exception.DaoException;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class StudentDaoImpl implements StudentDao {
    @Override
    public List<Student> selectAllStudents()  {
        List<Student> students=new ArrayList<>();
        BufferedReader reader=null;
        try {
            reader=new BufferedReader(new FileReader("students.txt"));
            String line;
            while ((line=reader.readLine())!=null){
                String[] strs=line.split("-");
                int id = Integer.parseInt(strs[0]);
                String name=strs[1];
                int age= Integer.parseInt(strs[2]);
                Student student =new Student(id,name,age);
                students.add(student);
            }

        }catch (IOException e){
            e.printStackTrace();
           throw new DaoException();
        }finally {
            if (reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                   e.printStackTrace();
                }
            }
        }

        return students;
    }

    @Override
    public void insertStudent(Student student)  {
        BufferedWriter writer =null;
        try {
            writer=new BufferedWriter(new FileWriter("students.txt", true));
            writer.write(student.getId()+"-");
            writer.write(student.getName()+"-");
            writer.write(student.getAge()+"");
            writer.newLine();
            writer.flush();

        }catch (Exception e){
            e.printStackTrace();
            throw new DaoException("Dao文件操作错误");
        }finally {
            if (writer!=null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
 

3.在service里面进行try catch的操作 在catch里面捕获DaoException ,throw new ServiceEXception

package com.woniuxy.service.impl;

import com.woniuxy.dao.StudentDao;
import com.woniuxy.dao.impl.StudentDaoImpl;
import com.woniuxy.entity.Student;
import com.woniuxy.exception.DaoException;
import com.woniuxy.exception.ServiceEXception;
import com.woniuxy.service.StudentService;

import java.io.IOException;
import java.util.List;

public class StudentServiceImpl implements StudentService  {
    public StudentDao studentDao=new StudentDaoImpl();

    @Override
    public void addStudent(Student student)  {
        try {
            studentDao.insertStudent(student);
        } catch (DaoException e) {
            e.printStackTrace();
            throw new ServiceEXception("Service操作错误,addStudent使用错误");
        }
    }

    @Override
    public List<Student> getAllStudents()  {
        try {
            studentDao.selectAllStudents();
            return studentDao.selectAllStudents();
        } catch (DaoException e) {
            e.printStackTrace();
            throw new ServiceEXception("Service操作错误,getAllStudents错误");
        }
    }

    @Override
    public void removeStudent(int id) {
        try {
            studentDao.deleteStudent(id);
        } catch (DaoException e) {
            e.printStackTrace();
            throw new ServiceEXception("Service操作错误,removeStudent错误");
        }
    }
}

ui 捕获的ServiceEXception 直接打印错误信息

package com.woniuxy.ui;

import com.woniuxy.entity.Student;
import com.woniuxy.exception.ServiceEXception;
import com.woniuxy.service.StudentService;
import com.woniuxy.service.impl.StudentServiceImpl;

import javax.script.ScriptContext;
import java.io.IOException;
import java.util.List;
import java.util.Scanner;

public class App {
     static Scanner scanner =new Scanner(System.in);
    static StudentService studentService=new StudentServiceImpl();
    public static void main(String[] args) throws IOException {
     getAllStudents();
//     addStudent();
    }

    private static void addStudent() throws IOException {
        try {
            System.out.println("添加学生");
            System.out.println("请输入学号");
            int id = scanner.nextInt();
            System.out.println("请输入姓名");
            String name =scanner.next();
            System.out.println("请输入年龄");
            int age = scanner.nextInt();
            Student student=new Student(id,name,age);
            studentService.addStudent(student);
        } catch (ServiceEXception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }

    }

    private static void getAllStudents()  {
        try {
            System.out.println(studentService.getAllStudents());
        } catch (ServiceEXception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }

}

e.getMessage是输出字符串里面的信息 类似下面这个

image-20221205131500580

删除

删除:I/O的API没有直接删除文件的方法
	
	
Dao
	delete(){
		//读数据
		//删除数据
		//写数据覆盖
	}
	
	
Dao
	读所有数据,转成集合
	
	批量添加:将集合数据写入文件覆盖
	
	
Service
	删除(){
		dao.读所有
		dao.批量添加()
	}

修改

service
    modify(Student student){
        //dao.读所有
        修改集合的元素 
        dao.批量添加()
    }

添加用户不能添加相同的id

ui
    输入数据
    展示
service
    业务层执行添加:
        判断id是否存在,存在才添加
dao
    基本的CRUD
    根据id查询
        Student getStduentById(int id);
            没有:null
            有:    new Student(xxx,xxx,xxx);
        List<Student> getAllStudents();
    添加

登录

表示层
    输入用户名,密码
业务逻辑层
    Admin login(String name,String pwd){
        //dao查询
        //判断用户名密码是否正确
        //错误提示:    用户名不存在;密码错误
        if(){
            new exception("用户名不存在")
        }
        if(){
            new exception("密码错误")
        }
        retrun admin;
    }
Dao
    //根据用户名查询密码
    String selectPwdByName(String name){
    }
    //根据主键查询管理员
    Admin selectAdminById(int id){
    }
    //根据用户名键查询管理员
    Admin selectAdminByName(String name){
    }

常见问题

Dao+Service
    接口+实现类,没有静态方法
UI    
    静态方法,为了方便,以后的web都没有static
业务逻辑层,不会有输入输出的相关代码,这些代码都是UI
Dao
    List<Student> getAllStudents(){
        //查询所有
    }
    Student getStudentById(int id){
        //根据id查询指定的学生
    }
    List<Student> getStudentsByFamilyName(String name){
        //读取每行文件,匹配相同的姓氏,封装对象,存入集合返回
    }

LoginService

public class AdminServiceImpl implements AdminService {
    AdminDao adminDao=new AdminDaoImpl();
    @Override
    public Admin login(String name, String pwd) {
        //根据用户名查询,返回密码
        try{
            Admin admin=adminDao.selectAdminByName(name);
            if(admin==null){
                throw new ServiceException("用户名不存在");
            }
            if(!admin.getPwd().equals(pwd)){
                throw new ServiceException("密码错误");
            }
            return admin;
        }catch (DaoException e){
            throw new ServiceException("联系管理员");
        }
    }
}

序列化和反序列化

序列化:对象存储到存储介质中
反序列化:将存储介质中的数据还原成对象

使用默认的二进制序列化必须实现接口Serializable

ObjectOutputStream
	直接将对象按照二进制格式写入文件
	public final void writeObject(Object obj)
ObjectInputStream
	读取序列化的二进制文件,还原成对象	
	public final Object readObject()

序列化结果有不同的形式
	二进制
	XML
	JSON
	
	
	
Exception in thread "main" java.io.InvalidClassException: com.woniuxy.io.Student; local class incompatible: stream classdesc serialVersionUID = -7256004073868010986, local class serialVersionUID = 6570981750800506245


序列化以后的文件,会记录这个保存的属性值以及这个类的所有属性的类型信息
反序列化的时候会检查文件中对应的类型,和要还原的类型是否一致,计算两边的serialVersionUID,不一致,反序列化失败
类中添加一个固定的值


transient关键字:定义属性时,使用这个关键字,序列化时,该属性的值,不会保存

image-20221206101337150

Properties

Properties是一个集合类,我们一般都是结合IO一起使用,在程序中,用它来充当配置文件。

Properties可以看出K和V都是String的Map

配置文件:将程序中要用到配置参数(固定的数据),手动写好一个文件。程序中需要使用这个数据,我们读取文件中的数据。

//取Properties集合中的key对应的value值
public String getProperty(String key) 

//一般都是加载我们手动写好的配置文件
public void load(Reader reader)

//set用的少
public Object setProperty(String key, String value)

//基本上不用
public void store(Writer writer, String comments)

装饰者模式

设计模式:
	软件开发的经验总结
	一类特定问题的一种解决方案
	
	
设计模式:可复用面向对象软件的基础
	GoF	总结了23个经典的设计模式
    
简单工厂:破坏了开闭原则
	一个父类,若干子类
	工厂类,静态方法,通过参数返回不同的子类对象
单例
	只创建一个对象
装饰者
	增强类的功能
	

增强类的功能
	继承:
		Coffee
			MilkCoffee
			SugarCoffee
			SaltCoffee
			MilkSugarCoffee
			//组合类型多,子类多
	

多线程

进程
    一个运行的程序就是一个进程
线程
    一个进程中的一条执行路径
    如果一个进程只有一条执行路径,就是单线程的程序
    如果一个进程只有多条执行路径,就是多线程的程序
Windows是多任务的操作系统    多个进程同时运行,并发执行
并行
    物理上的概念,同一时刻(时间点),多个任务同时执行
并发
    逻辑上的概念,一个时间段,多个任务同时执行

启动线程的四种方式

继承Thread类
实现Runnable接口
实现Callable接口
使用线程池

继承Thread类

1.自定义类,继承Thread类
2.重写run()方法
3.调用start()方法  //调用一个start()就开一个线程
    start()底层使用多线程的方式调用run()
    不要直接调用run(),是单线程
    
  MyThread t1=new MyThread();
  MyThread t2=new MyThread("MyThread02");//重写构造器 可以自定义名字
     t1.setName("MyThread01");//使用setname定义名字
     t1.start();
     t2.start();

实现Runnable接口

优点: java中的语法是单继承 ,多接口 如果已经继承了其他类就无法继承Thread类,使用可以实现Runnable接口。
1.自定义类实现Runnable接口,
2.重写run方法
3.MyRunnable myRunnable=new MyRunnable();
        Thread t1=new Thread(myRunnable);
        Thread t2=new Thread(myRunnable);
        t1.start();
        t2.start();

常用API

public final String getName()
    获取当前线程名
    
public static native Thread currentThread()
    获取当前线程对象
    
public void setName(String name)
    设置当前线程名,也可以定义带参构造器
    
public static void sleep(long millis) 
    线程休眠

Lambda表达式

lambda  方法的参数式接口
		方法(new 接口(){
			重写方法(){
			
			}
		})
		
		方法(()->{//实现代码})

public static <T> void sort(List<T> list, Comparator<? super T> c) 
//public static <T> void sort(List<T> list, Comparator<? super T> c)
        //语法糖:这个方法的第二个参数Comparator接口的实现类对象
        //关键就是实现接口中的方法,接口确定,重写的方法也就确定,这些都是可以推断出来的
        //Lambda表达式,就是对匿名内部类的进一步简化
        //(参数)->{方法体}
         //方法的参数类型可以省,如果方法体只有一条语句,retrun {}和;都可以省
        //只有个一个参数,()可以

序列化和反序列化例子

package com.woniuxy.io;
import com.sun.corba.se.pept.encoding.OutputObject;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class Test01 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        saveStudent();
        loadStudent();
        saveStudents();
        loadStudents();
    }
    private static void loadStudents() throws IOException, ClassNotFoundException {
        ObjectInputStream oos=new ObjectInputStream(new BufferedInputStream(new FileInputStream("students.bin")));
        List<Student> students= (List<Student>) oos.readObject();
        System.out.println(students);
        oos.close();
    }
    private static void saveStudents() throws IOException {
        List<Student> students=new ArrayList<>();
        students.add(new Student(1,"zs",12));
        students.add(new Student(2,"ls",11));
        students.add(new Student(3,"ww",13));
        ObjectOutputStream oos=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("students.bin")));
        oos.writeObject(students);
        oos.close();
    }
    private static void loadStudent() throws IOException, ClassNotFoundException {
        ObjectInputStream oos =new ObjectInputStream(
                new BufferedInputStream(new FileInputStream("student.bin")));
       Student student= (Student) oos.readObject();
        System.out.println(student);
        oos.close();
    }
    private static void saveStudent() throws  IOException{
        ObjectOutputStream oos=new ObjectOutputStream(
                new BufferedOutputStream(new FileOutputStream("student.bin")));
        oos.writeObject(new Student(1,"zs",12));
        oos.close();
    }
}

Properties

package com.woniuxy.io;

import javax.naming.Name;
import java.io.*;
import java.util.Properties;
import java.util.Set;

public class Test02 {
    public static void main(String[] args) throws IOException {
     test02();

    }

    private static void test03() throws IOException {
        Properties properties=new Properties();
        properties.setProperty("name", "zs");
        properties.setProperty("age", "12");
        properties.setProperty("email", "xxx@qq.com");
        //将properties集合中的key和value写入properties文件
        properties.store(new BufferedWriter(new FileWriter("xxx.properties" ) ),"自定义信息" );


    }

    private static void test02() throws IOException {
        Properties properties=new Properties();
        //properties.load是加载文件,读取配置信息
        properties.load(new BufferedReader(new FileReader("myproperties.txt")));
        System.out.println(properties.getProperty("id"));
        System.out.println(properties.getProperty("name"));
        System.out.println(properties.getProperty("age"));
        System.out.println(properties.getProperty("email"));
        //如果properties.getProperty("k") 是文件里面没有的,会输出空值
        //如果有着输出key对应的value
    }

    private static void test01() {
        //添加元素
        Properties properties=new Properties();
        properties.setProperty("id", "1");
        properties.setProperty("name", "zs");
        properties.setProperty("age", "12");
        //读取元素
        System.out.println(properties.getProperty("name"));
        //properties.stringPropertyNames()这个取的是所有的key的集合,
        //遍历key,通过properties.getProperty(key)可以获得所有value
        Set<String> strings = properties.stringPropertyNames();
        for (String str : strings) {
            System.out.println(str+"----"+ properties.getProperty(str));
        }

    }
}

Lambda –创建线程写法

package com.woniuxy.io;

import java.util.Collections;

public class Test05 {
    public static void main(String[] args) {

        for (int i = 1; i <= 10; i++) {
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
        // Thread第一种写法
        Thread t1 = new Thread() {
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "---" + i);
                }
            }

        };
        t1.start();
        //Thread第二种写法  匿名内部类
        new Thread() {
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "---" + i);
                }
            }
        }.start();

        //Runnable第一种写法
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "---" + i);
                }
            }
        }).start();

        //Runnable第二种写法lambda 写的一定是接口
        new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.println(Thread.currentThread().getName() + "---" + i);
            }
        }).start();


    }
}

lambda–Compartor集合排序

package com.woniuxy.io;
import java.sql.SQLOutput;
import java.util.*;

import static java.util.Comparator.*;

class StudentNameAsc implements Comparator<Student>{

    @Override
    public int compare(Student o1, Student o2) {
        return o1.getName().compareTo(o2.getName());
    }
}
public class Test06 {
    public static void main(String[] args) {
        List<Student> students=new ArrayList<>();
        Student s1=new Student(1,"zs",12);
        Student s2=new Student(2,"ls",11);
        Student s3=new Student(3,"ww",13);
        students.add(s1);
        students.add(s2);
        students.add(s3);
        System.out.println(students);
        //自定义类实现comparator接口,然后使用实现类进行升序排序
        Collections.sort(students, new StudentNameAsc());
        System.out.println(students);
        //使用匿名内部类进行 降序排序
        //语法糖,这个方法的第二个参数Comparator接口的实现类对象
        //关键就是实现接口中的方法,接口确定,重写的方法也就确定,
        //lambda表达式,就是对匿名内部类进一步简化
        Collections.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.getName().compareTo(o1.getName());
            }
        });
        System.out.println(students);
        // lambda表达式 (参数)->{方法体}
        Collections.sort(students, (Student o1, Student o2)-> {
            return o2.getName().compareTo(o1.getName());
    });
        System.out.println(students);
        //lambda表达式 (参数)->{方法体}
        //参数类型也可以省略,如果方法体只有一条语句,return {} 和;都可以省。
        Collections.sort(students, (o1, o2) -> o2.getName().compareTo(o1.getName()));
        System.out.println(students);

        //函数式编程
        //Comparator  compare(T t1, T t2);

    }


}

lambda–Collection.removeIf(Predicate)

package com.woniuxy.io;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class Test07 {
    public static void main(String[] args) {
        List<Student> students=new ArrayList<>();
        students.add(new Student(1,"zs",12));
        students.add(new Student(2,"ls",13));
        students.add(new Student(3,"ww",11));
        System.out.println(students);
        students.removeIf(new Predicate<Student>() {
            @Override
            public boolean test(Student student) {
                //false 都不删   true 都删了
                //可以自定义想删什么就删什么
                return student.getId()>=2;
            }
        });
        students.removeIf(student -> student.getId() >= 2);
//        students.removeAll(students);
        System.out.println(students);
    }
}

装饰者例子

package com.woniuxy.model;
//父类
class Coffee{
    public  String getCoffee(){
        return "coffee";
    }
}

//MilkCoffee子类继承父类Coffee
class MilkCoffee extends Coffee {
    //父类成员变量
    Coffee coffee;

    public MilkCoffee(Coffee coffee) {
        this.coffee = coffee;
    }
//装饰一下 z
    public String getCoffee() {
        return coffee.getCoffee() + "+milk";
    }
}

class SugarCoffee extends Coffee {
    Coffee coffee;

    public SugarCoffee(Coffee coffee) {
        this.coffee = coffee;
    }

    public String getCoffee() {
        return coffee.getCoffee() + "+Sugar";
    }
}
class SaltCoffee extends Coffee{
    Coffee coffee;

    public SaltCoffee(Coffee coffee) {
                this.coffee = coffee;
    }
    public  String getCoffee(){
                return coffee.getCoffee()+"+salt";
    }
}



public class Test01 {
    public static void main(String[] args) {
        Coffee coffee=new Coffee();
        System.out.println(coffee.getCoffee());
//sout  coffee
        MilkCoffee coffee1=new MilkCoffee(coffee);
        System.out.println(coffee1.getCoffee());
//sout  coffee+milk
        SugarCoffee coffee2=new SugarCoffee(coffee1);
        System.out.println(coffee2.getCoffee());
//sout  coffee+milk+Sugar
    }
}

1207

线程的启动执行具有随机性

多线程,获取cpu的执行权,
轮询机制:平均分配,轮流执行
java使用的抢占式:
	线程有优先级,获取cpu的执行概率大些

局部变量是安全的,每个都是自己的

影院卖票

不能超卖
不能重复卖票

为什么会出问题
	cpu一次只能保证一次执行一个完整的指令
	num--;一条语句的底层都对应多条语句
	一个线程抢到cpu,不能保证一个方法一次能从头到尾全部执行完,执行的过程中,可能被其他线程抢走cpu
	
如何判断多线程环境是否具有数据安全性问题
	1、多线程
	2、共享数据
	3、是否有语句修改共享数据
			sout(num);

如何解决
	加锁 synchronized  加在方法上面
	
	同步代码块
		多个线程,使用同一个锁对象
		synchronized(锁对象){
			//代码块
	 	}
	 	
	同步方法
	public synchronized void sellTicket(){}
	不想要指定锁对象,有默认的
		非静态方法:就是this
		静态方法:就是类的二进制字节码对象  对象.getClass()  类.class()   以后反射讲

单例设计多线程环境

饿汉  安全
	static Singleton singleton=new Singleton()  没问题
	
饱汉	不安全
 	public class Singleton {

        private static Singleton singleton;

        private Singleton(){}

        //double check 双重判断检查
        public static Singleton createInstance(){
            if(singleton==null){
               synchronized (SingletonRunnable.class){
                   if(singleton==null){
                       singleton=new Singleton();
                   }
               }
            }
            return  singleton;
        }
}
	

线程的生命周期

线程的生命周期包含5个阶段,包括:新建、就绪、运行、阻塞、死亡。
新建: 就是刚使用 new 方法,new 出来的线程;
Thread t1 = new Thread();

就绪: 就是调用的线程的 start() 方法后,这时候线程处于等待 CPU 分配资源阶段,谁先抢到 CPU 资源,谁开始执行;
t1.start()

运行: 当就绪的线程被调度并获得 CPU 资源时,便进入运行状态,run() 方法定义了线程的操作和功能;

阻塞: 在运行状态的时候,可能因为某些原因导致运行状态的线程变成了阻塞状态,比如 sleep()、wait() 之后线程就处于了阻塞状态,这个时候需要其他机制将处于阻塞状态的线程唤醒,比如调用 notify 或者 notifyAll() 方法。唤醒的线程不会立刻执行run 方法,它们要再次等待 CPU 分配资源进入运行状态;

死亡:线程会以以下三种方式之一结束,结束后就处于死亡状态:
	run()方法执行完成,线程正常结束。
线程抛出一个未捕获的Exception或Error。
直接调用该线程的stop()方法来结束该线程——该方法容易导致死锁,通常不推荐使用。

数据库

数据库就是数据的仓库,存储数据库。
底层还是按照一定格式存储到文件,使用记事本查看,乱码
数据库提供一套操作数据的编程语句SQL(Structured Query Language)机构化的查询语言

优点:保存大量数据
	 操作数据方便CRUD  增加(Create)、读取(Retrieve)、更新(Update)和删除(Delete)
	 保证数据的一致性和完整性  创建约束
	 给不同用户分配不同的操作权限

数据库技术的发展
	文件
	层次数据库 
	网状数据库
	关系型数据库  常用的
	支持面向对象的数据库 只有Oracle支持,一般都不会用,
	
常见的数据库
	产品  	   公司
	Oracle	    Oracle
	SQLServer 	Microsoft  
	MySQL       MySQL AB-->SUN-->Oracle
	DB2 		IBM
	Sybase		Sybase

下载

5.7
8.0
官网
https://dev.mysql.com/downloads/mysql/
国内镜像网站
https://developer.aliyun.com/mirror/

windows安装数据库
	安装版:
		.mis  .exe安装程序,下一步安装,指定安装路径(主要的文件安装以后都储存在这个位置,有些文件会保存到系统的指定目录,写入注册表)
	 安装失败,卸载,重装
	 
	绿色版
		解压使用,添加一些配置信息
	 安装失败,删了重装
		
进入服务 win+R  services.msc

没有安装过数据库 端口默认3306

装了一个之后,配置端口为3307

版权声明:本文为huangjiangyang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/huangjiangyang/p/16963276.html