数据库叠加

final

1.final 修饰类 类不可以被继承

2.final 修饰方法 方法不可以被重写

3.final 修饰局部变量

  1. 基本数据类型 值只能赋值一次,且不可改变了
  2. 引用数据类型 变量中保存的地址不可变,但是变量值可变

修饰符

权限修饰符本类同包子类不同包
public
protected
默认
private

内部类

一个类定义在另一个类中

public class Person{
	class Drink{
        public void water(){
            sout("此人在喝水!!");
        }
    }
}
public class PersonDemo01{
	public static void main(String[] args){
		Person p = new Person();
   //外部类.内部类 对象名= 外部对象名.new 内部类();
		Person.Drink d = p.new Drink();
		//调用内部类方法
		d.water();
	}
}

分类

package com.gxa.demo07;
/*
 * 内部类分类:
 * 成员内部类:
 * 静态内部类 static
 * 实例内部类 不加static
 * 局部内部类:定义在外部类的方法中的
 * 匿名内部类(重点!!!)
 */
public class MyInnerClass {
	//1.实例内部类
	class MyInner1{
		
	}
	
	//2.静态内部类
	static class MyInner2{
		
	}
	
	//3.局部内部类
	public void n(){
		class MyInner3{
			
		}
	}
	public static void main(String[] args) {
		//4.匿名内部类
		MyMath mm = new MyMath();
		//2.调用方法
		/*
		 * 匿名内部类写法:后面多线程创建中使用!!!
		 * new 接口名(){重写方法}
		 * 好处:1.简化自定义实现类的写法
		 * 坏处:1.可读性较差
		 */
		mm.mySum(new Compute() {//匿名内部类写法
			
			@Override
			public int sum(int a, int b) {
				
				return a+b;
			}
		}, 10, 20);
	}
}
//负责计算接口
interface Compute{
	//抽象方法
	int sum(int a,int b);
}
//Compute接口的实现类
/*class ComputeImpl implements Compute{

	@Override
	public int sum(int a, int b) {
		// TODO Auto-generated method stub
		return a+b;
	}
	
}*/
//数学类
class MyMath{
	//求和方法
	public void mySum(Compute c,int a,int b){
		int sum = c.sum(a, b);
		System.out.println(a+"+"+b+"="+sum);
	}
}

Object

toString()

简化输出,重新此方法

package com.gxa.demo08;
/*
 * Object是父类/超类/基类
 * 关于Object类toString()方法:
 * 1.源代码:
 *  public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    全类名(包名.类名)@对象的哈希码值/地址转为16进制的字符串
    2.SUN公司设计Object类toString()的目的?
    建议自定义类重写toString(),输出成员变量值就更加方便了
 */
public class ObjectDemo01 {
	public static void main(String[] args) {
		MyTime mt = new MyTime(2000, 1, 20);
		//1.没重写toString之前输出的结果:
		System.out.println(mt);//地址 com.gxa.demo08.MyTime@15db9742
		System.out.println(mt.toString());//地址 com.gxa.demo08.MyTime@15db9742
		//2.重写toString之后输出的结果:
		System.out.println(mt);//2000年1月20日
		System.out.println(mt.toString());//2000年1月20日
		System.out.println(mt.getYear()+"年"+mt.getMonth()+"月"+mt.getDay()+"日");
		//3.String字符串输出时输出的是内容,不是地址
		String s1 = new String("abc");
		System.out.println(s1);//abc
		String s2 = "def";
		System.out.println(s2);//def
	}
}
//时间类
class MyTime{
	private int year;
	private int month;
	private int day;
	
	public int getYear() {
		return year;
	}

	public void setYear(int year) {
		this.year = year;
	}

	public int getMonth() {
		return month;
	}

	public void setMonth(int month) {
		this.month = month;
	}

	public int getDay() {
		return day;
	}

	public void setDay(int day) {
		this.day = day;
	}

	public MyTime(int year, int month, int day) {
		super();
		this.year = year;
		this.month = month;
		this.day = day;
	}
	
	//重写toString()
	 public String toString() {
	        return this.year+"年"+this.month+"月"+this.day+"日";
	}
}

equals()

和hashCode()一起重写,比较引用数据类型的内容,重写此方法

package com.gxa.demo08;
/*
 * 关于Object类equals(Object obj)方法:
 * 1.源码:
 * public boolean equals(Object obj) {
        return (this == obj);
   }
   返回的比较地址后的布尔值
   2.SUN公司设计Object类equals(Object obj)的目的?
    建议自定义类重写equals(Object obj),重写后比较的就是内容就不再是地址了!!
 */
public class ObjectDemo03 {
	public static void main(String[] args) {
		MyLove ml1 = new MyLove("易烊千玺", 22, "hip-hop");
		MyLove ml2 = new MyLove("易烊千玺", 22, "hip-hop");
		//1.未重写equals()前:调用Object的equals()
		System.out.println(ml1.equals(ml2));//false
		System.out.println(ml1==ml2);//false
		//2.重写equals()后:调用MyLove的equals()
		System.out.println(ml1.equals(ml2));//true
		System.out.println(ml1==ml2);//false
		
	}
}

class MyLove{
	private String name;//String引用数据类型 比较值equals()
	private int age;//int基本数据类型 比较值==
	private String hobby;
	
	public MyLove() {
		super();
		// TODO Auto-generated constructor stub
	}
	public MyLove(String name, int age, String hobby) {
		super();
		this.name = name;
		this.age = age;
		this.hobby = hobby;
	}
	@Override
	public String toString() {
		return "MyLove [name=" + name + ", age=" + age + ", hobby=" + hobby + "]";
	}
	//快捷方式重写
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((hobby == null) ? 0 : hobby.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		MyLove other = (MyLove) obj;
		if (age != other.age)
			return false;
		if (hobby == null) {
			if (other.hobby != null)
				return false;
		} else if (!hobby.equals(other.hobby))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
	
	//手动重写
	/*public boolean equals(Object obj) {
		//1.如果obj是null或者不是mylove类型,没有必要比较,直接返回false
		if(obj==null||!(obj instanceof MyLove)){
			return false;
		}
		//2.如果this和obj保存的地址相同,没有必要比较,直接返回true
		if(this==obj){
			return true;
		}
		//3.程序执行到此,说明:obj不为null而且是MyLove类型,this和obj保存的地址不相同
		MyLove t = (MyLove)obj;
        return this.name.equals(t.name)&&this.age==t.age&&this.hobby.equals(t.hobby);
   }*/
}

finalize()

工作不会使用,笔试题中出现,当垃圾回收自动回收

package com.gxa.demo08;
/*
 * 关于Object类的finalize():——使用不到,笔试题考到
 * 1.源码:
 * protected void finalize() throws Throwable { }
 * 2.作用:
 * 当一个对象成为了垃圾需要被回收时,JVM的垃圾回收器会自动调用finalize(),
 * 不需要程序员手动调用
 * 3.Java的垃圾回收器不是轻易启动的,垃圾太少就不会回收,当垃圾达到一定数额才会回收
 * 或者建议垃圾回收器回收
 * 4. throws Throwable 抛出异常
 * 5.final finally finalize区别?——之后再讲
 * 
 */
public class ObjectDemo04 {
	public static void main(String[] args) {
		//1.创建对象
		/*God g = new God();
		//成为垃圾
		g = null;*/
		
		//2.多创造点垃圾
		/*for (int i = 0; i < 1000000000; i++) {
			God g = new God();
			//成为垃圾
			g = null;
		}*/
		
		//3.启动垃圾回收器
		/*God g = new God();
		//成为垃圾
		g = null;
		//public static void gc()
		System.gc();*///垃圾启动的概率变高
		
	}
}
//上帝类
class God{
	@Override
	protected void finalize() throws Throwable {
		System.out.println("世界由我创造,终将被我毁灭");
	}
}

clone()

面试题中出现,深克隆和浅克隆?

notify() notifyAll() wait()

3个在多线程中讲解

API

currentTimeMillis()

返回当前时间(以毫秒为单位)

Date()

java.util

package com.gxa.demo01;

import java.util.Date;

/*
 * java.util.Date:日期时间,工作中经常使用的!!!
 * 1.导包不要倒错,不是java.sql包下的Date
 * 2.构造方法——很多构造方法已弃用,不是不能使用,不建议使用!!!
 * public Date():创建对象
 * public Date(long date)
 * 3.成员方法
 * public long getTime()返回毫秒数
 */
public class DateDemo01 {
	public static void main(String[] args) {
		//Tue Feb 28 09:43:17 CST 2023  系统时间
		System.out.println(new Date());//匿名对象
		//Thu Jan 01 08:00:00 CST 1970
		System.out.println(new Date(0L));//匿名对象
		//返回毫秒数,自格林威治时间以来,1677549001591
		System.out.println(new Date().getTime());
	}
}

DateFormat()

日期/时间格式化子类的抽象类

SimpleDateFormat()

是一个以与语言环境有关的方式来格式化和解析日期的具体类。它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)和规范化。

public SimpleDateFormat(String pattern)

pattern:格式

日期格式
yyyyy
MMM
ddd
HHH
mmm
sss
S毫秒SSS
package com.gxa.demo01;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * 日格式化:
 * java.text.Format 格式化的抽象类
 * 		java.text.DateFormat 日期格式化的抽象类
 * 			java.text.SimpleDateFormat 日期格式化的类
 * 1.构造方法:
 * public SimpleDateFormat(String pattern) pattern:格式
 * 日期格式化元素:
 * y 年  yyyy
 * M 月  MM
 * d 日  dd
 * H 时  HH
 * m 分  mm
 * s 秒 ss
 * S 毫秒  SSS
 * 2.成员方法:
 * public final String format(Date d) Date——>String
 * public Date parse(String source)throws ParseException  String——>Date
 */
public class SDFDemo01 {
	public static void main(String[] args) throws ParseException {
		//1.创建日期格式化对象
		DateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS");//多态-向上转型
		//SimpleDateFormat sdf = new SimpleDateFormat();
		//2.格式化:Date——>String
		Date d = new Date();
		System.out.println(d);//Tue Feb 28 10:25:14 CST 2023
		System.out.println(df.format(d));//2023年02月28日 10:26:20 604
		//3.格式化:String——>Date
		String str = "2018年08月08日 08:08:08 888";
		System.out.println(df.parse(str));//Wed Aug 08 08:08:08 CST 2018
		
	}

}

Calendear()

package com.gxa.demo02;

import java.util.Calendar;
import java.util.Date;

/*
 * java.util.Calendar 抽象类
 * 1.不能直接new方式创建对象,但可以调用
 * public static Calendar getInstance()
 * 2.字段/属性/成员变量
 * public static final int YEAR 年
 * 3.成员方法
 * public int get(int field) 取出给定日历字段的值
 * public void set(int field,int value)设置日历字段的值
 * public abstract void add(int field,int amount)将指定的时间量添加或减去给定的日历字段
 * public final Date getTime() 转成Date类型
 */
public class CalendarDemo01 {
	public static void main(String[] args) {
		//Calendar c = new Calendar();
		//1.获得Calendar实例
		Calendar cal = Calendar.getInstance();
		//2.输出年月日,星期几:public int get(int field)
		int year = cal.get(Calendar.YEAR);
		System.out.println(year);//2023
		int month = cal.get(Calendar.MONTH)+1; //在Calendar中0~11表示中国的1~12
		System.out.println(month);//2
		int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
		System.out.println(dayOfMonth);//28
		System.out.println(cal.get(Calendar.DAY_OF_WEEK)-1);//2 在Calendar中周日是周一
		
		//3.设置日历字段的值 public void set(int field,int value)
		cal.set(Calendar.YEAR, 2005);
		int year1 = cal.get(Calendar.YEAR);
		System.out.println(year1);//2005
		
		//4.日历字段的值加/减去某个值
		cal.add(Calendar.YEAR, 2);
		int year2 = cal.get(Calendar.YEAR);
		System.out.println(year2);//2007
		
		//5.
		Date time = cal.getTime();
		System.out.println(time);//Wed Feb 28 11:39:57 CST 2007
		
	}
}

BigDecimal

package com.gxa.demo03;

import java.math.BigDecimal;

/*
 * BigDecimal:
 * 可以处理精度极高的数据,经常用在财务类软件中
 * java.lang.Number 
 * 		java.math.BigDecimal 
 * 1.构造方法
 * public BigDecimal(double val)
 * 2.成员方法:
 * public BigDecimal add(BigDecimal augend)
 */
public class BigDecimalDemo01 {
	public static void main(String[] args) {
		//1.创建对象
		BigDecimal v1 = new BigDecimal(10.89);
		BigDecimal v2 = new BigDecimal(10.11);
		//2.加法
		BigDecimal v3 = v1.add(v2);
		System.out.println(v3);
//		double d1 = 3.9;
//		double d2 = 4.1;
//		double d3 = d1+d2;
	}
}

DecimalFormat

package com.gxa.demo03;

import java.text.DecimalFormat;

/*
 * DecimalFormat数字格式化:
 * java.text.Format 
	java.text.NumberFormat 
		java.text.DecimalFormat 
	数字格式化元素:
	# 任意数字(0~9)
	. 小数点
	, 千分位
	0 不够的补零	
	
	public final String format(Object obj)
 */
public class DecimalFormatDemo01 {
	public static void main(String[] args) {
		//1.创建对象
		//加入千分位
		DecimalFormat df = new DecimalFormat("###,###");
		//2.格式化
		System.out.println(df.format(1234567));
		
		//3.创建对象
		//加入千分位,保留2位小数
		DecimalFormat df1 = new DecimalFormat("###,###.00");
		System.out.println(df1.format(1234567.123));//1,234,567.12
		//加入千分位,保留4位小数,不够的补零
		DecimalFormat df2 = new DecimalFormat("###,###.0000");
		System.out.println(df2.format(1234567.24));
		
	}
}

StringBuffer/StringBuilder

		StringBuffer b1 = new StringBuffer();
		StringBuffer bb3 = b1.append("jom23rgdstrh");
		System.out.println(bb3 == b1);
		System.out.println(b1);
		b1.append(k1).append(b4).append(f);
		System.out.println(b1);
package com.gxa.demo04;
/*
 * StringBuilder/StringBuffer:字符串缓冲区,这两个类解决字符串拼接浪费空间的问题
 * String声明的字符串,字符串一旦创建就不能改变,那么字符串拼接时很浪费内存空间
 * 1.构造方法:
 * public StringBuilder()
 * public StringBuilder(String str)
 * 2.成员方法
 * public StringBuilder append(String str)
 * public StringBuilder append(boolean b)
 * public StringBuilder append(double d)
 * 
 * 笔试题-选择题:
 * String StringBuilder StringBuffer
 * 相同:表示字符串,可以做字符串拼接使用
 * 不同:
 * String不可变的char[]数组,字符串拼接时很浪费内存空间
 * StringBuilder/StringBuffer 可扩容的字符序列,字符串拼接时不浪费内存空间
 * 
 * StringBuilder StringBuffer
 * 相同:
 * 1.使用时构造方法还是拼接字符串方法用法是相同,
 * 2.初始容量为16
 * 不同:
 * StringBuffer 多线程安全的(synchronized),效率低
 * StringBuilder 多线程不安全的,效率高
 */
public class StringBuilderDemo01 {
	public static void main(String[] args) {
		//1.创建对象
		StringBuilder b1 = new StringBuilder();
		//2.添加字符串
		StringBuilder b2 = b1.append("hello");
		System.out.println(b2);//hello
		System.out.println(b1==b2);//true b1和b2地址相同 append()方法添加字符串后,返回的就是对象本身
		StringBuilder b3 = b2.append(100);
		StringBuilder b4 = b3.append(true);
		System.out.println(b4);//hello100true
		//3.链式编程
		StringBuilder b5 = b1.append(12).append("java").append(3.14);
		System.out.println(b5);//hello100true12java3.14
	}
}

Integer

package com.gxa.demo05;
/*
 * 包装类Integer:
 * java.lang.Number 
		java.lang.Integer 
	此类包含一些类型转换的方法 String int Integer
	1.属性:
	public static final int MAX_VALUE
	public static final int MIN_VALUE
	2.构造方法:
	public Integer(int value)
	public Integer(String s)此字符串只能是数字类型的字符串
	3.成员方法
 */
public class IntegerDemo01 {
	public static void main(String[] args) {
		//1.属性
		System.out.println("最大值为:"+Integer.MAX_VALUE);
		System.out.println("最小值为:"+Integer.MIN_VALUE);
		
		//2.构造方法
		Integer i1 = new Integer(10);
		Integer i2 = new Integer("123");//此字符串只能是数字类型的字符串
		System.out.println(i1);//10
		System.out.println(i2);//123
		/*
		 * 以下代码报运行时异常:数字格式化异常
		 * NumberFormatException
		 */
		/*Integer i3 = new Integer("abc");
		System.out.println(i3);*///报异常
		
		//3.成员方法
		//String int Integer三个类型转换
		//1.int Integer
		//public static Integer valueOf(int i)
		Integer i4 = Integer.valueOf(10);
		//2.Integer-->int
		//public int intValue()
		int i5 = i4.intValue();
		//3.String-->Integer
		//public static Integer valueOf(String s)
		Integer i6 = Integer.valueOf("123");
		//4.Integer-->String
		String s = i6.toString();
		//5.String-->int
		//public static int parseInt(String s)
		int i7 = Integer.parseInt("123");
		//6.int-->String
		String s1 = 10+"";
	}
}

package com.gxa.demo05;
/*
 * JDK5.0新特性
 * 自动装箱(auto_boxing)和自动拆箱(auto_unboxing)
 */
public class IntegerDemo02 {
	public static void main(String[] args) {
		//JDK5.0之后
		Integer i1 = 10;//自动装箱
		int i2 = i1;//自动拆箱
		
		//JDK5.0之前
		Integer i4 = Integer.valueOf(10);
		int i5 = i4.intValue();
		
	}
}

package com.gxa.demo05;
/*
 * 自动装箱和自动拆箱笔试题:
 */
public class IntegerDemo03 {
	public static void main(String[] args) {
		Integer i1 = new Integer(10);
		Integer i2 = new Integer(10);
		System.out.println(i1==i2);//false
		System.out.println(i1.equals(i2));//true
		
		
		/*
		 * 笔试题:
		 * 如果数据值在-128~127范围之间,Java引入整型常量池
		 * 整型常量池只存储-128~127之间的数据
		 */
		Integer i3 = 128;
		Integer i4 = 128;
		System.out.println(i3==i4);//false
		
		Integer i5 = 127;
		Integer i6 = 127;
		System.out.println(i5==i6);//true
		
		String s1 = "abc";
		String s2 = "abc";
		System.out.println(s1==s2);//true
	}
}

File

package com.gxa.demo06;

import java.io.File;

/*
 * java.io.File:本地磁盘中文件或者目录抽象表示
 * 1.属性/字段/成员变量:
 * 
 */
public class FileDemo01 {
	public static void main(String[] args) {
		/*
		 * 操作路径:
		 * c:\a\b\a.txt  Windows
		 * c:/a/b/a.txt Linux
		 * "c:"+File.separator+"a"++File.separator+"b"+File.separator+"a.txt"
		 */
		String pathseparator = File.pathSeparator;
		System.out.println(pathseparator);//路径分隔符 windows系统中 ; Linux系统是 :
		System.out.println(File.pathSeparatorChar);//路径分隔符
		
		String separator = File.separator;
		System.out.println(separator);//\ 文件名称分隔符  windows系统中 \  Linux系统是 /
		System.out.println(File.separatorChar);//文件名称分隔符
	}
}

day2

File

package com.gxa.demo01;

import java.io.File;

/*
 * 1.路径:
 * 绝对路径:是以盘符开始完整的路径
 * D:\bj324\day13\src\com\gxa\demo01\FileDemo01.java
 * 相对路径:是一个简化的路径
 * day13\src\com\gxa\demo01\FileDemo01.java
 * 注意:
 * 1.路径没有大小写区分
 * 2.\是一个转义字符,在代码书写时路径分隔需要用两个\
 * 
 * 2.构造方法
 * public File(String pathname)使用得多
 * public File(String parent, String child)
 * public File(File parent,String child)
 */
public class FileDemo01 {
	public static void main(String[] args) {
		//1.public File(String pathname)
		//路径既可以是绝对也可以是相对路径,可以存在也可以是不存在的,可以文件也可以是文件夹结尾
		File f1 = new File("D:\\bj324\\day13\\src\\com\\gxa\\demo01\\FileDemo01.java");//绝对路径
		File f2 = new File("a.txt");//相对路径
		File f3 = new File("D:\\bj324\\day13\\src\\com\\gxa\\demo02");
		System.out.println(f1);//D:\bj324\day13\src\com\gxa\demo01\FileDemo01.java
		//2.public File(String parent, String child)
		File f4 = new File("c:\\","b.txt");
		System.out.println(f4);//c:\b.txt
		
		//3.public File(File parent,String child)
		File parent = new File("C:\\");
		File f5 = new File(parent,"c.txt");
		System.out.println(f5);//C:\c.txt
	}
}

package com.gxa.demo01;

import java.io.File;
import java.io.IOException;

/*
 * 创建/删除文件/文件夹-目录:重要!!!
 * public boolean createNewFile() throws IOException 创建文件
 * public boolean mkdir() 创建文件夹/目录
 * public boolean mkdirs() 创建多级文件夹/目录
 * public boolean delete() 删除文件/文件夹
 */
public class FileDemo02 {
	public static void main(String[] args) throws IOException {
		//1.创建文件1.txt
		File f1 = new File("D:\\bj324\\day13\\1.txt");//绝对路径
		boolean b1 = f1.createNewFile();
		System.out.println(b1);
		File f2 = new File("2.txt");//相对路径
		boolean b2 = f2.createNewFile();//默认创建在当前项目路径下
		System.out.println(b2);//true
		//createNewFile()只能创建文件,不能创建文件夹
		File f3 = new File("D:\\bj324\\day13\\a");
		f3.createNewFile();
		
		//2.创建文件夹
		File f4 = new File("D:\\bj324\\day13\\aaa");
		f4.mkdir();
		
		File f5 = new File("D:\\bj324\\day13\\aaa\\bbb\\ccc");
		f5.mkdirs();
		
		//3.删除文件/文件夹
		File f6 = new File("D:\\bj324\\day13\\a");
		f6.delete();
	}
}

package com.gxa.demo01;

import java.io.File;

/*
 * 判断是文件/文件夹:
 * public boolean isFile() 测试此抽象路径名表示的文件是否为普通文件
 * public boolean isDirectory()测试此抽象路径名表示的文件是否为目录。
 * public boolean exists()测试此抽象路径名表示的文件或目录是否存在。
 */
public class FileDemo03 {
	public static void main(String[] args) {
		File f1 = new File("D:\\bj324\\day13\\src\\com\\gxa\\demo01\\FileDemo01.java");//绝对路径
		System.out.println(f1.exists());//true
		File f2 = new File("D:\\bj324\\day13\\src\\com\\gxa\\demo01");
		System.out.println(f2.exists());
		
		System.out.println(f1.isFile());
		System.out.println(f1.isDirectory());
		System.out.println(f2.isFile());
		System.out.println(f2.isDirectory());
	}
}

package com.gxa.demo01;

import java.io.File;

/*
 * 获取方法:
 * 1.public File getAbsoluteFile() 获取绝对路径
 * 2.public String getName() 获取文件/文件夹名
 * 3.public String getPath() 获取路径
 */
public class FileDemo04 {
	public static void main(String[] args) {
		File f1 = new File("D:\\bj324\\day13\\src\\com\\gxa\\demo01\\FileDemo01.java");//绝对路径
		File f2 = new File("a.txt");//相对/不存在路径
		System.out.println(f1.getAbsolutePath());//D:\bj324\day13\src\com\gxa\demo01\FileDemo01.java
		System.out.println(f2.getAbsolutePath());//D:\bj324\day13\a.txt
		System.out.println(f1.getPath());//D:\bj324\day13\src\com\gxa\demo01\FileDemo01.java
		System.out.println(f2.getPath());//a.txt
		System.out.println(f1.getName());//FileDemo01.java
		System.out.println(f2.getName());//a.txt
	}
}

package com.gxa.demo01;

import java.io.File;

/*
 * 遍历文件夹/目录:重要
 * public String[] list()
 * public File[] listFiles()
 */
public class FileDemo05 {
	public static void main(String[] args) {
		//遍历D:\\jdk1.8.0_121文件
		File f1 = new File("D:\\jdk1.8.0_121");
		//1.File[] listFiles()
		File[] files1 = f1.listFiles();
		/*
		 * 增强for循环/foreach:
		 * for(数据类型  变量名:要遍历数组名/集合名){
		 * 		System.out.println(变量名);
		 * }
		 */
		for (File file : files1) {
			System.out.println(file.getName());//D:\\jdk1.8.0_121中的文件和文件夹名
		}
		
		/*int[] arr = {1,2,3,4};
		for (int i : arr) {
			System.out.println(i);
		}*/
		
		//2.String[] list()
		String[] list = f1.list();
		for (String s : list) {
			System.out.println(s);//D:\\jdk1.8.0_121中的文件和文件夹名
		}
		
	}
}

递归

package com.gxa.demo02;
/*
 * 直接递归:方法自己调用自己——工作中用的较少
 * 使用规则:
 * 1.递归一定要有限定结束的条件,否则会发生栈内存溢出:java.lang.StackOverflowError
 * 2.递归次数不能太多,否则会发生栈内存溢出:java.lang.StackOverflowError
 * 3.构造方法不能递归
 */
public class RecursionDemo01 {
	public static void main(String[] args) {
		//a();
		//b(1);
	}
	
	//3.构造方法不能递归
	/*public RecursionDemo01(){
		//this();//本类的无参构造
		RecursionDemo01();
	}*/
	
	//2.递归次数不能太多,否则会发生栈内存溢出:java.lang.StackOverflowError
	public static void b(int b){
		System.out.println(b);
		if(b==2000000){
			return;//结束b()
		}
		b(++b);//递归
	}
	
	//1.递归一定要有限定结束的条件,否则会发生栈内存溢出:java.lang.StackOverflowError
	public static void a(){
		System.out.println("a");
		a();
	}
	
}

package com.gxa.demo02;
/*
 * 练习:使用递归计算n!=n*(n-1)*(n-2)*...*1
 * 		使用递归计算n+(n-1)+(n-2)+...+1
 */
public class RecursionDemo02 {
	public static void main(String[] args) {
		int sum = sum(4);
		System.out.println(sum);//55
	}
	/*
	 * 递归结束条件
	 */
	public static int sum(int n){//4
		if(n==1){
			return 1;
		}
		return n+sum(n-1);//4 + sum(4-1) 3+sum(3-1) 2+sum(2-1) 1
	}
}

package com.gxa.demo02;

import java.io.File;

/*
 * 练习2:递归打印多级目录
 * 需求:遍历D:\bj324\day13,输出所有的子文件以及子文件夹
 */
public class RecursionDemo03 {
	public static void main(String[] args) {
		File f = new File("D:\\bj324\\day13");
		getFiles(f);
	}
	
	public static void getFiles(File dir){
		//System.out.println(dir);
		File[] files = dir.listFiles();
		for (File file : files) {//file可能是文件也可能是文件夹
			if(file.isDirectory()){//文件夹
				getFiles(file);//递归
			}else{//文件
				//只要以.java结尾的文件
				if(file.getName().endsWith(".java")){
					System.out.println(file);
				}
			}
			
		}
	}
}

文件过滤器

package com.gxa.demo02;

import java.io.File;
import java.io.FileFilter;

//过滤器实现类
public class FileFilterImpl implements FileFilter{

	@Override
	public boolean accept(File pathname) {//定义过滤规则
		if(pathname.isDirectory()){
			return true;
		}
		return pathname.getName().endsWith(".java");
	}
	
}

package com.gxa.demo02;

import java.io.File;
import java.io.FileFilter;

/*
 * 过滤器:Interface FileFilter和Interface FilenameFilter
 * FileFilter里面的抽象方法:
 * boolean accept(File pathname) 定义过滤规则
 * File类中遍历的方法:
 * public File[] listFiles(FileFilter filter)
 */
public class RecursionDemo04 {
	public static void main(String[] args) {
		File f = new File("D:\\bj324\\day13");
		getFiles(f);
	}
	
/*	public static void getFiles(File dir){
		FileFilter f = new FileFilterImpl();//多态
		File[] files = dir.listFiles(f);
		for (File file : files) {
			if(file.isDirectory()){//文件夹
				getFiles(file);
			}else{//文件:过滤器中过滤了.java文件
				System.out.println(file);
			}
		}
	}*/
	
	public static void getFiles(File dir){
		File[] files = dir.listFiles(new FileFilter() {//匿名内部类
			
			@Override
			public boolean accept(File pathname) {
				
				return pathname.isDirectory()||pathname.getName().endsWith(".java");
			}
		});
		for (File file : files) {
			if(file.isDirectory()){//文件夹
				getFiles(file);
			}else{//文件:过滤器中过滤了.java文件
				System.out.println(file);
			}
		}
	}
}

异常

package com.gxa.demo03;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;

/*
 * java.lang.Throwable:此类是Error(错误)和Exception(异常)的父类
 * Error(错误):相当于程序遇到了很严重的问题,唯一解决方式就是修改代码,避免错误发生
 * Exception :相当于程序遇到了小问题,
 * 编译期异常:写代码是报红,提示:unhandled Exception
 * throws抛出异常,或者try...catch捕获异常处理
 * 运行期异常(RuntimeException):运行代码后在控制台Console报红,提示:Exception
 * 修改代码,throws抛出异常,或者try...catch捕获异常处理
 * 
 * 记录异常获得财富!!!
 *   
 */
public class ExceptionDemo01 {
	public static void main(String[] args) throws ParseException, IOException{
		//1.编译期异常:ParseException IOException
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		sdf.parse("1995-01-28");
		File f1 = new File("D:\\bj324\\day13\\1.txt");//绝对路径
		boolean b1 = f1.createNewFile();
		
		//2.运行期异常
		//ArithmeticException-数学异常 ClassCastException-类型转换异常 
		//IndexOutOfBoundsException索引越界异常(ArrayIndexOutOfBoundsException , StringIndexOutOfBoundsException )
		//NullPointerException
	/*	int a = 10/0;
		System.out.println(a);*/
		
		//3.错误:java.lang.OutOfMemoryError
		//int[] arr = new int[1024*1024*1024];
		int[] arr = new int[1024*1024];
		System.out.println(111);
	}
}

package com.gxa.demo03;
/*
 * throw关键字:
 * 作用:指定的方法中抛出指定的异常(产生异常),一般用于自定义异常中
 * 异常:Java预定义异常,自定义异常
 * 格式:
 * throw new XXXException("异常产生的原因")
 * 注意:
 * 1.throw书写在方法的{}内部的
 * 2.创建的是Exception对象不是Error
 * 3.throw产生异常,就要解决此异常
 */
public class ExceptionDemo02 {
	public static void main(String[] args) {
//		int[] arr = null;
//		get(arr,0);
		int[] arr = new int[3];
		get(arr,2);
	}
	/*
	 * 对数组验证的方法
	 * 不符合验证条件的产生一个异常
	 */
	public static void get(int[] arr,int index){
		if(arr==null){
			throw new NullPointerException("此数组为null");//运行时异常RuntimeException
		}
		if(index>arr.length-1){
			throw new ArrayIndexOutOfBoundsException("数组索引超过了范围");
		}
		
	}
}

package com.gxa.demo03;

import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * throws关键字:处理异常的第一种方式,交给别人处理(推卸责任)
 * 作用:
 * 会把方法内部产生异常对象交给方法调用者处理(自己不处理,给别人处理),最终给JVM
 * 处理,进行中断处理
 * 注意:
 * 1.必须写在方法声明处
 * 2.throws 抛出的是一个异常
 * 3.当方法中产生了很多个异常,多个异常使用逗号隔离开
 * 4.当方法中产生了很多个异常并有父子关系时,只需要抛出父类异常
 */
public class ExceptionDemo03 {
	public static void main(String[] args) throws FileNotFoundException, IOException {
		getFile("c:\\a.txt");
	}
	/*
	 * 对文件的路径验证的方法
	 */
	public static void getFile(String pathName) throws IOException{
		if(!pathName.equals("c:\\c.txt")){
			throw new FileNotFoundException("传递文件路径不正确");//编译时异常
		}
		if(!pathName.endsWith(".java")){
			throw new IOException("文件名后缀不正确");
		}
	}
}

package com.gxa.demo03;

import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * try...catch:处理异常的第二种方式,自己处理-推荐
 * 格式:
 * try {
		产生异常的代码;
	}catch (XXXException1 e) {
		//打印异常信息
		e.printStackTrace();
	}catch (XXXException2 e) {
		//打印异常信息
		e.printStackTrace();
	}
 */
public class ExceptionDemo04 {
	public static void main(String[] args){
		try {
			getFile("c:\\a.txt");
		} catch (IOException e) {
			e.printStackTrace();//常用,打印异常信息最全面
			/*e.getMessage();
			e.toString() 不使用*/
		}
		
	}
	/*
	 * 对文件的路径验证的方法
	 */
	public static void getFile(String pathName) throws IOException{
		if(!pathName.equals("c:\\c.txt")){
			throw new FileNotFoundException("传递文件路径不正确");
		}
		if(!pathName.endsWith(".java")){
			throw new IOException("文件名后缀不正确");
		}
	}
}

package com.gxa.demo03;

import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * finally{}代码块:
 * 格式:
 * 	try {
		产生异常的代码;
	}catch (XXXException1 e) {
		//打印异常信息
		e.printStackTrace();
	}catch (XXXException2 e) {
		//打印异常信息
		e.printStackTrace();
	}finally{
		一定会执行
	}
	注意:
	1.finally{}不能单独使用,和try一起使用
	2.finally{}用于资源释放(回收),使用在IO流中——后面会讲到
	
	笔试题:
	final finalize finally的区别?
	final是修饰符,修饰类类不能被继承,修饰方法不能被重写,修饰局部变量不可变
	finalize()是方法,垃圾回收系统自动调用的方法,无需程序员关心
	finally{}是代码块,用于资源释放(回收)
 */
public class ExceptionDemo05 {
	public static void main(String[] args) {
		try {
			getFile("d:\\a.txt");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			System.out.println("aaa");
            System.exit(0)//jvm虚拟机关闭,
			//ps.close();
		}
	}
	
	/*
	 * 对文件的路径验证的方法
	 */
	public static void getFile(String pathName) throws IOException{
		if(!pathName.equals("c:\\c.txt")){
			throw new FileNotFoundException("传递文件路径不正确");
		}
		if(!pathName.endsWith(".java")){
			throw new IOException("文件名后缀不正确");
		}
	}
}

package com.gxa.demo03;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;

/*
 * 异常处理注意1:
 * 1.多个异常分别处理
 * 2.多个异常一次try,多个catch:子类异常写在父类异常上面
 * 3.多个异常有父子类关系时,一个try,一个catch
 */
public class ExceptionDemo06 {
	public static void main(String[] args) {
		/*try{
			int[] arr = {1,2,3};
			System.out.println(arr[5]);
		}catch(ArrayIndexOutOfBoundsException e){
			e.printStackTrace();
		}
		try{
			ArrayList<Integer> list = new ArrayList<>();
			list.add(1);
			list.add(2);
			list.add(3);
			System.out.println(list.get(4));
		}catch(IndexOutOfBoundsException e){
			e.printStackTrace();
		}*/
		/*try{
			
			int[] arr = {1,2,3};
			System.out.println(arr[5]);
			ArrayList<Integer> list = new ArrayList<>();
			list.add(1);
			list.add(2);
			list.add(3);
			System.out.println(list.get(4));
		}catch(ArrayIndexOutOfBoundsException e){//子类异常写在父类异常上面
			e.printStackTrace();
		}catch(IndexOutOfBoundsException e){
			e.printStackTrace();
		}*/
		
		try{
			
			int[] arr = {1,2,3};
			System.out.println(arr[5]);
			ArrayList<Integer> list = new ArrayList<>();
			list.add(1);
			list.add(2);
			list.add(3);
			System.out.println(list.get(4));
		}catch(IndexOutOfBoundsException e){
			e.printStackTrace();
		}
		
	}
}

package com.gxa.demo01;
/*
 * 1.父类中方法抛出异常,
 * 子类重写父类方法时可以不抛出异常或者抛出和父类相同的异常或者抛出父类异常的子类
 * 2.父类方法没有抛出异常,
 * 子类重写父类方法时子类方法中有异常,此时只能try...catch,不能throws
 */
//父类
public class Fu {
	public void show01() throws NullPointerException,ArithmeticException{};
	public void show02() throws Exception{}
	public void show03(){}
}
//子类
class Zi extends Fu{
	public void show01() throws NullPointerException,ArithmeticException{}

	public void show02() throws RuntimeException{}
	
	public void show03(){
		try {
			throw new Exception("XXX");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
package com.gxa.demo02;
/*
 * 自定义异常:
 * 1.自定义异常类名以Exception结尾
 * 2.必须继承Exception/RuntimeException
 * 3.必须添加一个无参构造方法
 * 4.必须添加一个带异常信息的构造方法
 */
//登录异常
public class LoginException extends Exception{

	public LoginException() {
		super();
	}

	public LoginException(String message) {
		super(message);
	}
}

package com.gxa.demo02;

import java.util.Scanner;

/*
 * 登录时,输入用户名,用户名不存在,提示:请先注册,才可以登录
 */
public class LoginDemo01 {
	public static void main(String[] args) {
		//1.定义数组保存已经存在用户名
		String[] usernames = {"甄嬛","华妃","皇后"};
		//2.可以使用Scanner输入登录用户名
		Scanner sc = new Scanner(System.in);
		String username = sc.next();
		check(username, usernames);
	}
	public  static void check(String username,String[] usernames){
		//遍历数组,取出用户名
		for (String name : usernames) {
			if(!name.equals(username)){
				try {
					throw new LoginException("请先注册,才可以登录");
				} catch (LoginException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

day3

Collection

package com.gxa.demo03;

import java.util.ArrayList;
import java.util.Collection;

/*
 * Collection常用方法:
 */
public class CollectionDemo01 {
	public static void main(String[] args) {
		//1.创建集合对象——多态
		Collection<String> coll = new ArrayList<>();
		//2.添加元素
		coll.add("嬛嬛");
		coll.add("甄嬛");
		coll.add("孙俪");
		System.out.println(coll);//[嬛嬛, 甄嬛, 孙俪]
		//3.判断是否包含某个元素
		System.out.println(coll.contains("嬛嬛"));//true
		//4.删除元素
		System.out.println(coll.remove("嬛嬛"));
		//5.元素个数
		System.out.println(coll.size());//2
		
		//6.遍历集合
		/*for (int i = 0; i < coll.size(); i++) {
			System.out.println(coll.get(i));
		}*/
		for (String s : coll) {
			System.out.println(s);
		}
		
		Object[] array = coll.toArray();
		for (int i = 0; i < array.length; i++) {
			System.out.println(array[i]);
		}
		
		//7.清空元素,判断集合是否为空
		coll.clear();
		System.out.println(coll.isEmpty());//true
	}
}

package com.gxa.demo03;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/*
 * 迭代器Iterator遍历集合
 * Iterface Iterable<E>可迭代接口
 * Iterator<T> iterator()获取迭代器
 * Iterface Iterator<E>迭代器接口
 * boolean hasNext()判断是否有元素可迭代
 * E next() 取出元素
 */
public class CollectionDemo02 {
	public static void main(String[] args) {
		Collection<String> coll = new ArrayList<String>();
		coll.add("肖战");
		coll.add("王一博");
		coll.add("蔡徐坤");
		//使用迭代器遍历
		//1.获取迭代器
		Iterator<String> it = coll.iterator();
		while(it.hasNext()){
			String s = it.next();
			System.out.println(s);
		}
	}
}

泛型

泛型类
package com.gxa.demo04;
/*
 * 自定义泛型类:当你不确定类存储什么数据类型,就可以定义为一个泛型类
 * public class ArrayList<E>
 * 	public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    	}
    }
 */
public class GenericClass<E> {
	private E name;

	public E getName() {
		return name;
	}

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

package com.gxa.demo04;
/*
 * 泛型是使用此泛型类时规定是什么数据类型
 */
public class GenericClassDemo01 {
	public static void main(String[] args) {
		GenericClass<String> s = new GenericClass<>();
		s.setName("王麻子");
	}
}

泛型方法
package com.gxa.demo05;
/*
 * 自定义泛型方法
 * 修饰符 <M> 返回值  方法名(M m){
 */
public class GenericMethod {
	
		public <M> void method01(M m){
			System.out.println(m);
		}
}

package com.gxa.demo05;
/*
 * 使用/调用方法时规定泛型类型
 */
public class GenericMethodDemo01 {
	public static void main(String[] args) {
		GenericMethod gm = new GenericMethod();
		gm.method01(10);
		gm.method01("abc");
	}
}

泛型接口
package com.gxa.demo06;
/*
 * 自定义泛型接口
 */
public interface GenericInterface<I> {
	/*public abstract*/ void m(I i);
}

package com.gxa.demo06;

public class GenericInterfaceImpl implements GenericInterface<String>{

	@Override
	public void m(String i) {
		System.out.println(i);
		
	}

}

package com.gxa.demo06;

public class GenericInterfaceImpl1<I> implements GenericInterface<I>{

	@Override
	public void m(I i) {
		System.out.println(i);
		
	}

}
class Demo01{
	public static void main(String[] args) {
		GenericInterfaceImpl1<Integer> gi = new GenericInterfaceImpl1<>();
		gi.m(10);
	}
}
package com.gxa.demo07;

import java.util.ArrayList;
import java.util.Collection;
/*
 * ?:泛型通配符
 */
public class GenericDemo01 {
	public static void main(String[] args) {
        Collection<Integer> list1 = new ArrayList<Integer>();
        Collection<String> list2 = new ArrayList<String>();
        Collection<Number> list3 = new ArrayList<Number>();
        Collection<Object> list4 = new ArrayList<Object>();

        getElement1(list1);
//        getElement1(list2);//报错
        getElement1(list3);
//        getElement1(list4);//报错

        //getElement2(list1);//报错
        //getElement2(list2);//报错
        getElement2(list3);
        getElement2(list4);

    }
    // 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
    public static void getElement1(Collection<? extends Number> coll){}
    // 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
    public static void getElement2(Collection<? super Number> coll){}
}

可变参数与addAll()
package com.gxa.demo08;

import java.util.ArrayList;
import java.util.Collections;

/*
 * 可变参数:
 * 书写在方法的参数列表中,格式:数据类型... 变量名
 * 使用条件:
 * 可变参数放在参数列表中只能有一个
 * 可变参数放在参数列表中的最后面
 */
public class VarArgsDemo01 {
	public static void main(String[] args) {
		sum1(10,20,30,40,50);
		ArrayList<Integer> list = new ArrayList<>();
		Collections.addAll(list, 10,20,30,40,50);
		System.out.println(list);//[10, 20, 30, 40, 50]
	}
	//自定义一个方法:求两个整数的和
/*	public static void sum1(int a,int b){
		System.out.println(a+b);
	}
	//自定义一个方法:求三个整数的和
	public static void sum1(int a,int b,int c){
		System.out.println(a+b+c);
	}*/
	//自定义一个方法:可变参数
	public static void sum1(int...a){//int...a 相当于int[] a
		System.out.println(a);//[I@15db9742 数组的地址
		System.out.println(a.length);//5
		int sum = 0;
		for (int i = 0; i < a.length; i++) {
			sum += a[i];
		}
		System.out.println(sum);
	}
	
	//可变参数放在参数列表中的最后面
	public static void a(double b,boolean c,int...a){
		
	}
	//可变参数放在参数列表中只能有一个
	/*public static void b(double...b,int...a){
		
	}*/
}

day4

list接口

  • 有序,存入的顺序和取出顺序相同
  • 可重复,存储的元素值可相同
  • 有索引:可for遍历
package com.gxa.demo01;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/*
 * List接口:
 * 特点:
 * 1.有序,可重复
 * 2.有索引,普通for遍历
 * 
 * 特有的方法:
 * E get(int index)
 * void add(int index,E element) 插入
 * E set(int index,E element) 替换
 * ListIterator<E> listIterator() List集合的迭代器
 */
public class ListDemo01 {
	public static void main(String[] args) {
		List<String> list = new ArrayList<>();
		list.add("a");
		list.add("d");
		list.add("c");
		list.add("a");
		System.out.println(list);//[a, d, c, a]
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		for (String s : list) {
			System.out.println(s);
		}
		Iterator<String> it = list.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
		
		ListIterator<String> li = list.listIterator();
		while(li.hasNext()){
			System.out.println(li.next());
		}
	}
}

  1. arrayList
    package com.gxa.demo01;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.LinkedList;
    
    /*
     * ArrayList集合特点:
     * 1.底层的数据结构是数组:查询快,增删慢
     * transient Object[] elementData;
     * 2.初始容量:10
     * public ArrayList() 初始容量为10
     * public ArrayList(int initialCapacity) 指定初始容量
     * 3.扩容方式:原容量的1.5倍
     * private void grow(int minCapacity) {
            // overflow-conscious code
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity + (oldCapacity >> 1);//1.5oldCapacity
            elementData = Arrays.copyOf(elementData, newCapacity);
      }
      4.非线程安全的集合
      
      	特有方法:
      	ArrayList() 构造一个初始容量为十的空列表。  
    	ArrayList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。  
    	ArrayList(int initialCapacity) 构造具有指定初始容量的空列表。  
    
     */
    public class ArrayListDemo01 {
    	public static void main(String[] args) {
    		LinkedList<Integer> list = new LinkedList<>();
    		list.add(1);
    		list.add(3);
    		ArrayList<Integer> arr = new ArrayList<>(list);
    	}
    }
    
    
  2. LinkedLIst
    package com.gxa.demo01;
    
    import java.util.Collections;
    import java.util.LinkedList;
    
    /*
     * LinkedList集合特点:
     * 1.底层数据结构双向链表:查询慢,增删快
     *   private static class Node<E> {//双向链表中节点
            E item;//数据域
            Node<E> next;//后继指针
            Node<E> prev;//前继指针
         }
     * 2.没有初始容量和扩容方式
     * 3.非线程安全的集合
     * 4.API大量操作首尾元素的方法
     * 
     * 构造方法:
     * 	LinkedList() 构造一个空列表。  
    	LinkedList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。  
            成员方法:
    	public void addFirst(E e)在该列表开头插入指定的元素。
    	public void addLast(E e)将指定的元素追加到此列表的末尾。
    	public E pop() 此方法相当于removeFirst() 。 
    	public void push(E e)此方法相当于addFirst(E) 。
     */
    public class LinkedListDemo01 {
    	public static void main(String[] args) {
    		LinkedList<String> list = new LinkedList<>();
    		Collections.addAll(list, "abc","bcd","cde","def");
    		System.out.println(list);
    		list.addFirst("111");
    		list.addLast("222");
    		list.pop();
    		list.push("333");
    		System.out.println(list);
    	}
    }
    
    
    1. vector
    package com.gxa.demo01;
    
    import java.util.Enumeration;
    import java.util.Vector;
    
    /*
     * Vector集合:工作中不使用,笔试题中出现
     * 特点:
     * 1.数组
     * 2.初始容量:10
     * 3.扩容2倍
     * 4.线程安全,但效率低,不使用
     * 成员方法:
     * public void addElement(E obj)
     * public boolean removeElement(Object obj)
     * public Enumeration<E> elements()
     * boolean hasMoreElements() 测试此枚举是否包含更多元素。  
     * E nextElement() 如果此枚举对象至少有一个要提供的元素,则返回此枚举的下一个元素。  
     */
    public class VectorDemo01 {
    	public static void main(String[] args) {
    		Vector<Integer> v = new Vector<>();
    		v.addElement(1);
    		v.addElement(10);
    		v.addElement(5);
    		v.addElement(2);
    		Enumeration<Integer> e = v.elements();
    		while(e.hasMoreElements()){
    			System.out.println(e.nextElement());
    		}
    	}
    }
    
    
    package com.gxa.demo01;
    
    import java.util.Enumeration;
    import java.util.Vector;
    
    /*
     * Vector集合:工作中不使用,笔试题中出现
     * 特点:
     * 1.数组
     * 2.初始容量:10
     * 3.扩容2倍
     * 4.线程安全,但效率低,不使用
     * 成员方法:
     * public void addElement(E obj)
     * public boolean removeElement(Object obj)
     * public Enumeration<E> elements()
     * boolean hasMoreElements() 测试此枚举是否包含更多元素。  
     * E nextElement() 如果此枚举对象至少有一个要提供的元素,则返回此枚举的下一个元素。  
     */
    public class VectorDemo01 {
    	public static void main(String[] args) {
    		Vector<Integer> v = new Vector<>();
    		v.addElement(1);
    		v.addElement(10);
    		v.addElement(5);
    		v.addElement(2);
    		Enumeration<Integer> e = v.elements();
    		while(e.hasMoreElements()){
    			System.out.println(e.nextElement());
    		}
    	}
    }
    
    

Set接口

  • 无序

  • 不可重复

  • 没有索引

    HashSet
package com.gxa.demo02;

import java.util.HashSet;
import java.util.Set;

/*
 * Set集合:
 * 1.元素无序,不可重复
 * 2.没有索引,不能使用普通for循环
 */

public class SetDemo01 {
	public static void main(String[] args) {
		//Set
		Set<Integer> set = new HashSet<>();
		set.add(1);
		set.add(3);
		set.add(2);
		set.add(1);
		for (Integer i : set) {
			System.out.println(i);//1 2 3
		}
	}
}

package com.gxa.demo02;

import java.util.HashSet;

/*
 * HashSet(HashMap)集合:
 * 1.无序,不可重复
 * 2.无索引
 * 3.哈希表数据结构:数组+链表+红黑树(JDK1.8之后)
 *  HashSet/HashMap集合存储数据/元素不可重复原理?
 *  当添加数据时,首先会调用hashCode计算数据的哈希码值,把哈希码值
 *  一样分为一组,然后再调用equals比较哈希码值相同的数据内容,如果内容不相同
 *  就会用链表连接,当链表长度超过8就转为红黑树存储数据
 */
public class HashSetDemo01 {
	public static void main(String[] args) {
		//HashSet
		HashSet<String> set = new HashSet<>();
		String s1 = new String("abc");
		String s2 = new String("abc");
		set.add(s1);
		set.add(s2);
		set.add("重地");
		set.add("通话");
		set.add("abc");
		System.out.println(s1.hashCode());//96354
		System.out.println(s2.hashCode());//96354
		System.out.println("重地".hashCode());//1179395
		System.out.println("通话".hashCode());//1179395
		System.out.println("abc".hashCode());//96354
		System.out.println(set);
	}
}

package com.gxa.demo02;

public class Person {
	private String name;
	private int age;
	
	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 Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	
	
}

LinkedHashSet
package com.gxa.demo02;

import java.util.LinkedHashSet;
/*
 * LinkedHashSet集合:
 * 1.有序:存储和取出元素顺序相同
 * 2.不可重复
 * 3.数据结构:哈希表+链表
 */
public class LinkedHashSetDemo01 {
	public static void main(String[] args) {
		LinkedHashSet<String> set = new LinkedHashSet<>();
		set.add("www");
		set.add("abc");
		set.add("gxa");
		set.add("www");
		set.add("com");
		System.out.println(set);
	}
	
}

collection工具类

package com.gxa.demo03;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

/*
 * Collections单列集合工具类:
 * 1.public static <T> boolean addAll(Collection<? super T> c,T... elements) 添加元素
 * 2.public static <T> void fill(List<? super T> list,T obj)替换集合中元素
 * 3.public static void reverse(List<?> list) 反转集合中的元素
 * 4.public static void shuffle(List<?> list)打乱元素顺序
 */
public class CollectionsDemo01 {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		Collections.addAll(list, 1,2,10,9,5,8);
		System.out.println(list);
		Collections.reverse(list);
		System.out.println(list);
		Collections.shuffle(list);
		System.out.println(list);
		Collections.fill(list, 666);
		System.out.println(list);
		
	}
}

Comparable
package com.gxa.demo03;

public class Person implements Comparable<Person>{
	private String name;
	private int age;
	
	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 Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	
	@Override
	public int compareTo(Person o) {
		//按照年龄升序排序
		//return this.age-o.age;
		//按照年龄降序排序
		return o.age-this.age;
	}
	
	
	
}

package com.gxa.demo03;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;

/*
 * Collections
 * 排序方法:
 * 1.public static <T extends Comparable<? super T>> void sort(List<T> list)
 * 集合存储的自定义类型时,自定义类实现Comparable<自定义类型>,并且重写抽象方法compareTo()
 * 在此方法中定义比较规则,升序 return this.age-o.age;,降序return o.age-this.age;
 * 2.public static <T> void sort(List<T> list,Comparator<? super T> c)
 * Comparable 可比较接口  Comparator比较器
 * 排序:如果是数字按照数字大小排序,如果是字母按照字母表顺序,中文不参与排序
 */
public class CollectionsDemo02 {
	public static void main(String[] args) {
		/*HashSet<Integer> set = new HashSet<>();
		Collections.addAll(set, 12,1,10,7,8);
		ArrayList<Integer> list = new ArrayList<>(set);*/
		
		ArrayList<Integer> list = new ArrayList<>();
		Collections.addAll(list, 1,7,3,5,10,2);
		System.out.println(list);//[1, 7, 3, 5, 10, 2]
		Collections.sort(list);
		System.out.println(list);//[1, 2, 3, 5, 7, 10]
		
		ArrayList<Person> list1 = new ArrayList<>();
		list1.add(new Person("小樱桃", 18));
		list1.add(new Person("小丸子", 28));
		list1.add(new Person("小新", 8));
		System.out.println(list1);
		//按照年龄排序
		Collections.sort(list1);
		System.out.println(list1);
	}
}

comparator
package com.gxa.demo03;

public class Student {
	private String name;
	private int age;
	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;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	
}

package com.gxa.demo03;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/*
 * 2.public static <T> void sort(List<T> list,Comparator<? super T> c)
 * Comparator比较器使用匿名内部类,重写
 * Comparable 可比较接口  Comparator比较器compare(Student o1, Student o2)方法,
 * 在此方法定义比较规则:升序- o1.getAge()-o2.getAge(); 降序序- o2.getAge()-o1.getAge();
 * 排序:如果是数字按照数字大小排序,如果是字母按照字母表顺序,中文不参与排序
 */
public class CollectionsDemo03 {
	public static void main(String[] args) {
		ArrayList<Student> list = new ArrayList<>();
		list.add(new Student("a小樱桃", 18));
		list.add(new Student("c小丸子", 28));
		list.add(new Student("b小新", 18));
		System.out.println(list);
		Collections.sort(list, new Comparator<Student>() {
			
			//定义比较规则
			@Override
			public int compare(Student o1, Student o2) {
				/*//按照年龄升序
				return o1.getAge()-o2.getAge();*/
				//按照年龄升序
				//return o2.getAge()-o1.getAge();
				//按照年龄升序排序,年龄相同的按照姓名的首字母排序
				int result = o1.getAge()-o2.getAge();
				if(result==0){
					result = o1.getName().charAt(0)-o2.getName().charAt(0);
				}
				return result;
			}
		});
		System.out.println(list);
	}
}

day5

map

package com.gxa.demo01;

import java.util.HashMap;
import java.util.Map;

/*
 * 1.Map<K,V>集合:
 * 特点:
 * key无序不可重复,value可重复
 * 方法:
 * V put(K key,V value)存储数据
 * V remove(Object key) 删除数据
 * V get(Object key)获取数据
 * boolean containsKey(Object key) 是否有某个键
 * boolean containsValue(Object value) 是否有某个值
 */
public class MapDemo01 {
	public static void main(String[] args) {
		//1.创建对象
		Map<String, Integer> map = new HashMap<>();
		//2.存储数据
		map.put("小馒头", 22);
		map.put("小花卷", 22);
		map.put("小红豆", 32);
		map.put("小红豆", 33);
		//3.直接map
		System.out.println(map);//{小红豆=32, 小花卷=22, 小馒头=12}
		//3.根据key取出value
		System.out.println(map.get("小红豆"));//32
		//4.删除
		map.remove("小花卷");
		System.out.println(map);
		//5.判断
		System.out.println(map.containsKey("小画卷"));//false
		System.out.println(map.containsValue(32));//true
	}
}

map遍历

package com.gxa.demo01;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
 * Map集合遍历第一种方式:通过key找到value
 * 方法:
 * Set<K> keySet() 把Map集合中的key取出来放到Set集合中
 * V get(Object key)根据key获取value
 * 步骤:
 * 1.创建对象,使用keySet() 把Map集合中的key取出来放到Set集合中
 * 2.遍历Set集合取出每一个key
 * 3.使用get(Object key)根据key获取value
 */
public class MapDemo02 {
	public static void main(String[] args) {
		Map<Integer, Integer> map = new HashMap<>();
		map.put(1, 2);
		map.put(2, 3);
		map.put(3, 4);
		map.put(4, 5);
		Set<Integer> set = map.keySet();
		for (Integer key : set) {
			Integer value = map.get(key);
			System.out.println(key+"="+value);
		}
	}
}

package com.gxa.demo01;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/*
 * Map集合遍历第二种方式:通过获取键值对遍历
 * 方法:
 * Map接口
 * Set<Map.Entry<K,V>> entrySet() 把Map集合中的键值对取出来放到Set集合中
 * Map.Entry<K,V>键值对接口:
 * K getKey() 获取key
 * V getValue() 获取value
 * 步骤:
 * 1.创建对象,使用entrySet() 把Map集合中的键值对取出来放到Set集合中
 * 2.遍历Set集合取出每一个键值对
 * 3.使用K getKey() 获取key 和 V getValue() 获取value
 */
public class MapDemo03 {
	public static void main(String[] args) {
		Map<String,Integer> map = new HashMap<>();
		map.put("小樱桃", 20);
		map.put("小旋风", 29);
		map.put("小花花", 25);
		Set<Entry<String, Integer>> set = map.entrySet();
		for (Entry<String, Integer> entry : set) {
			String key = entry.getKey();
			Integer value = entry.getValue();
			System.out.println(key+"="+value);
		}
	}
}

HashMap<K,V>

  • 底层数据结构是哈希表(数组+链表+红黑树)
  • 初始化容量:16
  • 默认加载因子0.75
  • 扩容方式:2倍
  • key无序不可重复的(和HashSet存储特点一致)
  • key和value存储空null
  • 非线程安全

注意:

在new HashSet()<>()时,底层是在new HaspMap<>();

调用HashSet的add方法存储数据时,底层是向HashMap中的key

package com.gxa.demo02;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/*
 * HashMap<K,V>集合:
 * 特点:
 * 1.数据结构:哈希表(数组+链表+红黑树jdk1.8)
 * 位桶数组
 * transient Node<K,V>[] table;
 * 链表中的节点:
 *   static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;
     }
 * 2.初始容量:16
 * 3.默认加载因子:0.75
 * static final float DEFAULT_LOAD_FACTOR = 0.75f;
 * 4.扩容方式:2倍
 * 5.key无序不可重复的(和HashSet存储特点一致)
 * 6.key和value存储空null
 * 7.非线程安全
 * 
 * 注意:
 * 1.在new HashSet<>();时,底层是在new HashMap<>();
 *  public HashSet() {
        map = new HashMap<>();
    }
   2.调用HashSet的add()方法存储数据时,底层是向HashMap中的Key存储数据
     public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    
     public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
 */
public class HashMapDemo01 {
	public static void main(String[] args) {
		//1.特点:
		HashMap<String, Integer> map = new HashMap<>();
		map.put("1", 1);
		map.put("1", 2);
		map.put("1", 3);
		map.put(null, null);
		System.out.println(map);//{null=null, 1=3}
		//2.数据结构:哈希表(数组+链表+红黑树)
		map.put("重地", 10);
		map.put("通话", 10);
		System.out.println(map);//{null=null, 1=3, 重地=10, 通话=10}
		
		//3.遍历:ketSet() entrySet()
	}
}

package com.gxa.demo02;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;

/*
 * HashMap<K,V>集合:
 * 一)特点:
 * 1.数据结构:哈希表(数组+链表+红黑树jdk1.8)
 * 位桶数组
 * transient Node<K,V>[] table;
 * 链表中的节点:
 *   static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;
     }
     树中的节点:
     static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
        TreeNode<K,V> parent;  // red-black tree links
        TreeNode<K,V> left;
        TreeNode<K,V> right;
        TreeNode<K,V> prev;  
 * 2.初始容量:16
 * static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
 * 3.默认加载因子:0.75
 * static final float DEFAULT_LOAD_FACTOR = 0.75f;
 * 4.扩容方式:2倍
 * 5.key无序不可重复的(和HashSet存储特点一致)
 * 6.key和value存储空null
 * 7.非线程安全
 * 
 * 注意:
 * 1.在new HashSet<>();时,底层是在new HashMap<>();
 *  public HashSet() {
        map = new HashMap<>();
    }
   2.调用HashSet的add()方法存储数据时,底层是调用HashMap的put方法向Key存储数据
     public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    
     public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    h = key.hashCode()) ^ (h >>> 16) 首先调用key的hashCode()方法计算出hash值,hash值^hash值右移16位
    计算数据放在位桶数组哪个位置
    final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
   key.equals(k)其次调用key的equals方法比较内容,如果内容不一致使用链表节点存储,当节点大于8时
   使用红黑树
   
   	二)方法:
   	HashMap() 构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。  
	HashMap(int initialCapacity) 构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)。  
	HashMap(int initialCapacity, float loadFactor) 构造一个空的 HashMap具有指定的初始容量和负载因子。  
	HashMap(Map<? extends K,? extends V> m) 构造一个新的 HashMap与指定的相同的映射 Map 。  

 */
public class HashMapDemo01 {
	public static void main(String[] args) {
		//1.特点:
		HashMap<String, Integer> map = new HashMap<>();
		map.put("1", 1);
		map.put("1", 2);
		map.put("1", 3);
		map.put(null, null);
		System.out.println(map);//{null=null, 1=3}
		//2.数据结构:哈希表(数组+链表+红黑树)
		map.put("重地", 10);
		map.put("通话", 10);
		System.out.println(map);//{null=null, 1=3, 重地=10, 通话=10}
		
		//3.遍历:ketSet() entrySet()
	}
}

自定义类型,不可重复性

package com.gxa.demo02;

public class Person {
	private String name;
	private int age;
	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 Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
	
	
}

package com.gxa.demo02;

public class Student {
	private String name;
	private int age;
	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 Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

package com.gxa.demo02;

import java.util.HashMap;

/*
 * HashMap存储自定义类型:
 * 1.key是自定义类型:满足key无序,不可重复,需要重写hashcode和equals
 * 2.value是自定义类型:value值可以重复,不需要重写hashcode和equals
 */
public class HashMapDemo02 {
	public static void main(String[] args) {
		//1.key是自定义类型:满足key无序,不可重复
		HashMap<Person, String> map = new HashMap<>();
		map.put(new Person("左璧莹", 33), "东北人");
		map.put(new Person("高圆圆", 43), "北京人");
		map.put(new Person("左璧莹", 33), "四川人");
		System.out.println(map);
		
		//2.value是自定义类型:value值可以重复
		HashMap<String, Student> map1 = new HashMap<>();
		map1.put("东北人", new Student("左璧莹", 33));
		map1.put("四川人", new Student("左璧莹", 33));
		System.out.println(map1);//map1.put("东北人", new Student("左璧莹", 33));
	}
}

Properties

LinkedHashMap

package com.gxa.demo03;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;

/*
 * LinkedHashMap<K,V>
 * 特点:
 * 1.底层数据结构:哈希表+链表
 * 2.有序:存储和取出元素顺序一致
 */
public class LinkedHashMapDemo01 {
	public static void main(String[] args) {
		LinkedHashSet<Integer> set = new LinkedHashSet<>();
		set.add(10);
		set.add(20);
		set.add(15);
		System.out.println(set);//[10, 20, 15]
		
		LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>();
		map.put(10, 2);
		map.put(18, 2);
		map.put(9, 2);
		map.put(12, 2);
		System.out.println(map);//{10=2, 18=2, 9=2, 12=2}
		
		HashMap<Integer, Integer> hash = new HashMap<>();
		hash.put(1, 2);
		hash.put(2, 3);
		hash.put(9, 1);
		hash.put(5, 6);
		hash.put(17, 6);
		hash.put(8, 2);
		hash.put(3, 6);
		hash.put(20, 6);
		hash.put(4, 2);
		//{1=2, 2=3, 3=6, 4=2, 5=6, 8=2, 9=1}
		//{1=2, 17=6, 2=3, 3=6, 20=6, 4=2, 5=6, 8=2, 9=1}
		//是和HashMap的初始容量16和默认加载因子0.75有关,有时按照key升序,有时又不是!!!
		System.out.println(hash);//HashMap可以按照key排序,可排序集合——错误说法
		
	}
}

HashTable

package com.gxa.demo03;

import java.util.Hashtable;
import java.util.Map;

/*
 * HashTable<K,V>集合:在工作中不使用,但是笔试时遇到!!
 * 	1.底层数据结构是哈希表(数组+链表+红黑树)
 *  private transient Entry<?,?>[] table;
 *  private static class Entry<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Entry<K,V> next;
	2.初始化容量:11
	3.默认加载因子:0.75
	    public Hashtable() {
        this(11, 0.75f);
    }
	4.扩容方式:2倍+1
	5.线程安全,效率低,不使用
	6.key和value不允许为null
	
	注意:ConcurrentHashMap!!!面试考点
	Hashtable是同步的。 如果不需要线程安全的实现,建议使用HashMap代替Hashtable 。
	 如果需要线程安全的并发实现,那么建议使用ConcurrentHashMap代替Hashtable 。 

 */
public class HashTableDemo01 {
	public static void main(String[] args) {
		Hashtable<String, Integer> table = new Hashtable<>();
		//以下代码报:java.lang.NullPointerException
		table.put(null, 1);
		table.put("abc", null);
		System.out.println(table);
	}
}

TreeSet/TreeMap

package com.gxa.demo03;

import java.util.Comparator;
import java.util.TreeMap;
import java.util.TreeSet;
/*
 * TreeSet/TreeMap集合
 * 1.数据结构:树
 * public V put(K key, V value) {
        Entry<K,V> t = root;
        if (t == null) {
            compare(key, key); // type (and possibly null) check

            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        Entry<K,V> parent;
        // split comparator and comparable paths
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
 *  public TreeSet() {
        this(new TreeMap<E,Object>());
    }
    public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }
    2.可排序:按照key大小进行排序
    3.key是无序:存储和取出的顺序不一致
 */


public class TreeSetDemo01 {
	public static void main(String[] args) {
		//无序,可排序集合
		TreeSet<Integer> set = new TreeSet<>();
		set.add(10);
		set.add(1);
		set.add(9);
		set.add(8);
		set.add(3);
		set.add(7);
		System.out.println(set);//[1, 3, 7, 8, 9, 10]
		
		TreeMap<Integer, String> map = new TreeMap<>();
		map.put(10, "aaa");
		map.put(8, "aaa");
		map.put(9, "aaa");
		map.put(6, "aaa");
		map.put(5, "aaa");
		System.out.println(map);//{5=aaa, 6=aaa, 8=aaa, 9=aaa, 10=aaa}
	
	}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8e3OIuUk-1679486971881)(day11.assets/image-20230306152258106.png)]

Thread线程

package com.gxa.demo05;
/*
 * 多线程:
 * 1.并发和并行:
 * 并发:多个事件在同一时间段内发生
 * 并行:多个事件在同一时刻发生
 * 2.进程(面试题)
 * 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,
 * 一个应用程序可以同时运行多个进程;
 * 进程也是程序的一次执行过程,是系统运行程序的基本单位;
 * 系统运行一个程序即是一个进程从创建、运行到消亡的过程。
 * 3.线程(面试题)
 * 线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。
 * 一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。 
 *进程和线程的关系?
 *简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 
 * 4.线程的调度
 * 分为两类:分时调度(平均分配)  抢占式调度(谁抢到CPU时间片谁先执行,会让优先级高的线程抢到的概率变大)
 * Java中的多个线程是并发执行的,是抢占式调度
 */
public class ThreadDemo01 {

}

package com.gxa.demo05;
/*
 * 创建线程的第一种方式:继承Thread
 * 1.定义Thread的子类,并且重写该类的run()方法
 * run()方法是定义线程要执行的任务
 * 2.创建线程类对象
 * 3.调用start()方法启动线程
 * 
 * 注意:
 * 1.加入多线程课程后,JVM内存,方法区,堆,主栈(主线程main),分支栈(自定义线程)
 * 2.main方法本身就是一个线程,成为主线程
 */
//两个线程之间是抢占式调度,谁先抢到CPU,谁先执行,所以运行结果:有先有后,有多有少
public class ThreadDemo02 {
	public static void main(String[] args) {//主线程
		//创建线程对象
		MyThread01 mt = new MyThread01();
		//启动线程
		mt.start();
		
		//主栈
		for (int i = 0; i < 60; i++) {
			System.out.println("main-"+i);
		}
	}
}

//自定义线程类
class MyThread01 extends Thread{
	@Override
	public void run() {//线程任务
		//分支栈
		for (int i = 0; i < 50; i++) {
			System.out.println("MyThread01——"+i);
		}
	}
}


package com.gxa.demo05;
/*
 * 创建线程的第三种方式:匿名内部类——简化实现类
 * 创建线程的第四种方式(面试题):Lamdba表达式(JDK8.0)——简化匿名内部类
 */
public class ThreadDemo04 {
	public static void main(String[] args) {
		//public Thread(Runnable target)
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < 10; i++) {
					System.out.println("t-"+i);
				}	
			}
		});
		
		t.start();
	}
}

package com.gxa.demo05;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/*
 * 创建线程的第五种方式:实现Callable接口
 * Class FutureTask<V> implements Runnable:
 * FutureTask(Callable<V> callable) 
 * Interface Callable<V>接口
 * V call()计算一个结果
 * 
 * 缺点:书写麻烦  好处:call()线程任务方法有返回值
 */
@SuppressWarnings("all")
public class ThreadDemo05 {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		//1.创建FutureTask<V>对象,定义线程任务
		FutureTask task = new FutureTask(new Callable() {
			@Override
			public Object call() throws Exception {
				//线程任务求和
				int a = 100;
				int b = 200;
				return a+b;
			}
		});
		
		//2.创建对象,启动线程
		public Thread(Runnable target)
		Thread t = new Thread(task);//多态
		t.start();
		
		//3.接收返回值
		Object object = task.get();
		System.out.println("和为:"+object);
	}
}

day6

线程名字

package com.gxa.demo01;
/*
 * 线程中常用方法1:——获取线程对象,取名字
 * public static Thread currentThread() 返回对当前正在执行的线程对象的引用。
 * public final void setName(String name)将此线程的名称更改为等于参数name 。
 * public final String getName()返回此线程的名称。
 * public Thread(Runnable target,String name)构造方法,给线程取名字
 */
public class ThreadDemo01 {
	public static void main(String[] args) {
		Thread t = new Thread(new MyThread01());
		t.setName("花花");
		t.start();
		
		Thread t1 = new Thread(new MyThread01());
		t1.setName("朵朵");
		t1.start();
	}
}
//自定义线程类
class MyThread01 extends Thread{
	@Override
	public void run() {
		Thread t = Thread.currentThread();
		System.out.println(t.getName());//Thread-1  花花

	}
}

线程优先级

package com.gxa.demo01;
/*
 * 线程中常用方法2:——线程的优先级(1-10)
 * 最低 1  最高10  默认5
 * 优先让优先级高额线程抢占CPU时间片的时间相对多一些
 * public static final int MAX_PRIORITY 线程可以拥有的最大优先级。
 * public static final int MIN_PRIORITY 线程可以拥有的最小优先级
 * public static final int NORM_PRIORITY分配给线程的默认优先级。 
 * public final void setPriority(int newPriority) 更改此线程的优先级。
 * public final int getPriority()返回此线程的优先级。 
 */
public class ThreadDemo02 {
	public static void main(String[] args) {
		System.out.println(Thread.MAX_PRIORITY);//10
		System.out.println(Thread.MIN_PRIORITY);//1
		System.out.println(Thread.NORM_PRIORITY);//5
		
		Thread t1 = new Thread(new MyThread02());
		t1.setName("t1");
		Thread t2 = new Thread(new MyThread02());
		t2.setName("t2");
		t1.setPriority(10);
		t2.setPriority(1);
		System.out.println(t1.getPriority());//10
		System.out.println(t2.getPriority());//1
		t1.start();
		t2.start();
	}
}
class MyThread02 extends Thread{
	@Override
	public void run() {
		for (int i = 0; i < 50; i++) {
			System.out.println(Thread.currentThread());
		}
	}
}

线程休眠

package com.gxa.demo01;
/*
 * 线程中常用方法3:——线程休眠(重要)
 * public static void sleep(long millis) throws InterruptedException使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),
 * 1.静态方法
 * 2.抛出异常InterruptedException
 * 3.参数:毫秒值
 * 4.作用:让当前线程进入睡眠状态,放弃之前占用的CPU时间片,让给其他线程使用
 * 5.场景:间隔一定时间执行一段代码
 */
public class ThreadDemo03 {
	public static void main(String[] args) {//main方法-主线程
		try {
			Thread.sleep(1000*5);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		for (int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName()+"---"+i);
		}
	}
}

线程中断

package com.gxa.demo01;
/*
 * 线程中常用方法3:——终止线程休眠
 * 线程睡太久了,中途醒来
 * public void interrupt()终止休眠,会在控制台报异常
 */
public class ThreadDemo04 {
	public static void main(String[] args) {
		Thread t = new Thread(new MyThread04());
		t.setName("睡美人");
		t.start();
		//5秒后醒来
		//5秒后
		try {
			Thread.sleep(1000*5);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//醒来
		t.interrupt();
	}
}
class MyThread04 implements Runnable{

	@Override
	public void run(){
		System.out.println(Thread.currentThread().getName()+"---begin");
		try {
			Thread.sleep(365*24*60*60*1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"---end");
		
	}
	
}
package com.gxa.demo01;
/*
 * 线程中常用方法5:—— 终止线程执行
 * public final void stop() 线程不安全,已被弃用,不建议使用
 * 合理终止线程执行,可以写布尔标记方式
 */
public class ThreadDemo05 {
	public static void main(String[] args) {
		MyThread05 mt  = new MyThread05();
		Thread t = new Thread(mt);
		t.setName("t");
		t.start();
		//5秒后终止线程
		try {
			Thread.sleep(1000*5);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//终止线程
		mt.run = false;
	}
}
class MyThread05 implements Runnable{
	//写布尔标记
	boolean run = true;
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			if(run){//true 执行线程任务
				System.out.println(Thread.currentThread().getName()+"---"+i);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}else{
				//false 终止当前线程=终止run
               
				return;
				
			}
		}
		
	}
	
}

线程执行有顺序

  • join();
  • 可以协调线程之间的同步运行(大扫除:先扫地,再拖地)
  • 同步和异步
  • 同步:运行有先后顺序,加join();
  • 异步:运行没有顺序,多个线程并发执行
package com.gxa.demo01;
/*
 * 线程中常用方法6:—— 线程执行有顺序
 * public final void join() throws InterruptedException
 * 该方法可以协调线程之间的同步运行(大扫除:先扫地,再拖地)
 * 同步和异步:
 * 同步:运行有先后顺序,加join()
 * 异步:运行没有顺序,多个线程并发执行
 * 
 * 举例:先下载图片,再显示图片
 */
public class ThreadDemo06 {
	private static boolean isFinish = false;
	public static void main(String[] args) {
		//1.下载线程
		Thread download = new Thread(new Runnable() {
			
			@Override
			public void run() {
				System.out.println("download:开始下载图片....");
				for (int i = 1; i <=100; i++) {
					System.out.println("download:"+i+"%");
					try {
						Thread.sleep(40);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				isFinish = true;
			}
		});
		
		//2.显示线程
		Thread show = new Thread(new Runnable() {
			
			@Override
			public void run() {
				
				try {
					/*
					 * show线程加到download线程后面,
					 * show线程中调用download.join();,此时show线程
					 * 处于阻塞状态,直到download执行完毕show线程接触阻塞
					 */
					download.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("show:显示图片");
				if(!isFinish){
					throw new RuntimeException("加载图片失败");
				}
			}
		});
		
		//3.运行
		download.start();
		show.start();
	}
}

yield

作用:当前运行的进程让出cpu时间片回到就绪状态,回到就绪状态还可以和其他的线程继续抢占cpu时间片

线程的状态(6种)

  • NEW,RUNNABLE,BLOCKED,WAITING,TIME_WAITING,TERMINATED
  • 新建,可运行(就绪),阻塞,无限等待,有限等待,(terminated)销毁态
public static void yield()

守护线程

线程分为前台线程和后台线程,后台线程为收获线程,自定义线程为前台线程

若想变成后台线程,调用一下方法,即可变为后台线程:

public final void setDaemon(boolean o) 参数为true

  • 注意:
  • 守护线程使用上没有区别
  • 守护线程结束的标志:所有的前台线程结束,守护线程才会结束
package com.gxa.demo01;
/*
 * 线程中常用方法8:—— 守护线程
 * 线程分为前台线程和后台线程,后台线程又称谓守护线程,自定义线程和主线程都是前台线程,
 * 调用以下方法即可变为守护线程:
 * public final void setDaemon(boolean on) 参数为true
 * 
 * 注意:
 * 1.守护线程和前台线程使用方法和创建没有区别,
 * 守护线程结束的标志:所有的前台线程结束,守护线程才会结束
 * 泰坦尼克号:
 * 肉丝(前台)和杰克()后台
 * 2.public final boolean isDaemon() 判断是否是守护线程
 * 3.gc垃圾回收器
 */
public class ThreadDemo08 {
	public static void main(String[] args) {//主线程-前台线程
		//1.肉丝线程
		Thread rose = new Thread(new Runnable() {
			
			@Override
			public void run() {
				//让我死
				for (int i = 0; i < 5; i++) {
					System.out.println("rose:let me go!!");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				System.out.println("rose:啊啊啊啊啊啊");
				System.out.println("rose:噗通,死了");
			}
		});
		
		//2.杰克线程
		Thread jack = new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true){
					System.out.println("you go i go");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
			}
		});
		
		//3.启动
		rose.start();
		
		//4.Jack变为守护线程
		jack.setDaemon(true);
		jack.start();
		
		while(true){
			
		}
	}
}

线程安全

多线程并发执行线程安全问题出现的条件

  1. 多个线程
  2. 共享的数据
  3. 对共享的数据有修改的操作

解决线程安全

  1. 同步代码块 synchronized(obj){}//obj对象锁(定义在类中方法外的共享对象)

    package day8;
    
    public class Ticket implements Runnable{
    	private int  ticket = 20;
    	Object obj = new Object();
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		while(true) {
    			synchronized (obj) {
    				if(ticket > 0) {
    					System.out.println(Thread.currentThread().getName() + "正在买票....." + ticket--);
    					try {
    						Thread.sleep(1000);
    					} catch (InterruptedException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}
    				}
    			
    			}
    		}
    		
    		
    		
    	};
    	
    
    }
    
    
    package day8;
    
    public class TicketDemo {
    	public static void main(String[] args) {
    		Ticket ticket = new Ticket();
    		Thread t1 = new Thread(ticket,"窗口1");
    		Thread t2 = new Thread(ticket,"窗口2");
    		Thread t3 = new Thread(ticket,"窗口3");
    		t1.start();
    		t2.start();
    		t3.start();
    		
    	}
    
    }
    
    
  2. 同步方法

    `

    package com.gxa.demo02;
    /*
     * 线程安全问题:
     * 1.多个线程
     * 2.操作共享数据
     * 3.对共享的数据有修改操作
     * 
     * 解决线程安全问题方式:
     * 1.同步代码块
     * 2.同步方法
     * 3.Lock锁
     */
    //票——线程类
    public class Ticket implements Runnable{
    	//共享的数据
    	private int ticket = 1000;
    	Object obj = new Object();
    	@Override
    	public void run() {//卖票窗口开启卖票
    		
    		while(true){
    		
    		//1.同步代码块
    			/*synchronized(obj){//obj 对象锁(定义在类中方法外的共享对象)
    				if(ticket>0){
    					//出票时间
    					try {
    						Thread.sleep(300);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					//卖票
    					System.out.println(Thread.currentThread().getName()+"正在售卖:"+ticket--);
    					}
    				}
    			}*/
    			//2.同步方法
    			sellTicket();
    		
    		}
    	}
    	
    	public synchronized void sellTicket(){
    		if(ticket>0){
    			//出票时间
    			try {
    				Thread.sleep(300);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			//卖票
    			System.out.println(Thread.currentThread().getName()+"正在售卖:"+ticket--);
    			}
    		}
    }
    
    
    
  3. Lock锁

ReentrantLock

lock() unlock()

.lock 加锁
.unlock()释放锁

package day8;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Ticket implements Runnable{
	private int  ticket = 200;
	Lock lock = new ReentrantLock();

	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		while(true) {
			lock.lock();
			if(ticket > 0) {
				System.out.println(Thread.currentThread().getName() + "正在买票....." + ticket--);
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			lock.unlock();
		
			}
		}
}

package com.gxa.demo03;
/*
 * 抢银行案例
 */
//账户类
public class Account {
	private String actNo;//账号
	private double balance;//余额
	Object obj = new Object();
	
	public Account(String actNo, double balance) {
		super();
		this.actNo = actNo;
		this.balance = balance;
	}
	public Account() {
		super();
		// TODO Auto-generated constructor stub
	}
	public String getActNo() {
		return actNo;
	}
	public void setActNo(String actNo) {
		this.actNo = actNo;
	}
	public double getBalance() {
		return balance;
	}
	public void setBalance(double balance) {
		this.balance = balance;
	}
	
	//取款方法
	//public synchronized void withdraw(double money){//取得钱
	public  void withdraw(double money){
		//synchronized (obj) {//同步锁/对象锁
			//synchronized (this) {//同步锁/对象锁
			//1.取款前的余额
			double before = this.getBalance();
			//2.取款后的余额
			double after = before - money;
			//3.延迟
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//4.更新余额
			this.setBalance(after);
		//}
		
	}
}
//取款线程
class PPP implements Runnable{
	
	//共享的账户
	private Account act;
	
	public PPP(Account act) {
		super();
		this.act = act;
	}

	@Override
	public void run() {//表示开始取款
		synchronized (act) {//act是共享的对象
			act.withdraw(1000.0);
		}
		System.out.println(Thread.currentThread().getName()+"对"+act.getActNo()+"取款1000.0元成功,余额为:"+act.getBalance());
		
	}
}
package com.gxa.demo03;

public class AccountDemo01 {
	public static void main(String[] args) {
		//1.创建共享的账户对象
		Account act = new Account("act-001",3000.0);
		//2.创建线程
		PPP p = new PPP(act);
		Thread t1 = new Thread(p,"小左");
		Thread t2 = new Thread(p,"小何");
		//3.启动
		t1.start();
		t2.start();
	}
}

day7

死锁

package com.gxa.demo01;
/*
 * 死锁:
 * 多个线程同时被阻塞状态,它们中的一个或者全部线程都在等待资源被释放。
 * 由于无限期被阻塞,程序不能正常终止
 * sychronized同步代码块发生嵌套
 */
public class ThreadDemo01 {
	public static void main(String[] args) {
		Object o1 = new Object();
		Object o2 = new Object();
		Thread t1 = new MyThread1(o1, o2);
		Thread t2 = new MyThread2(o1, o2);
		t1.start();
		t2.start();
	}
}

//线程1
class MyThread1 extends Thread{
	Object o1;//同步锁1
	Object o2;//同步锁2
	
	public MyThread1(Object o1, Object o2) {
		super();
		this.o1 = o1;
		this.o2 = o2;
	}
	
	@Override
	public void run() {
		synchronized (o1) {
			for (int i = 0; i < 10; i++) {
				System.out.println(Thread.currentThread().getName()+"---"+i);
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			synchronized (o2) {
				
			}
		}
		
	}
}

//线程2
class MyThread2 extends Thread{
	Object o1;//同步锁1
	Object o2;//同步锁2
	public MyThread2(Object o1, Object o2) {
		super();
		this.o1 = o1;
		this.o2 = o2;
	}
	
	@Override
	public void run() {
		synchronized (o2) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			synchronized (o1) {
				
			}
		}
	}
}

定时器

package com.gxa.demo01;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/*
 * 使用定时器完成定时任务
 * java.util.Timer 每隔一段时间执行一段任务
 * 构造方法:
 * public Timer()
 * public Timer(boolean isDaemon)isDaemon为true,守护线程/后台线程使用
 * 成员方法:
 * public void schedule(TimerTask task,Date time)
 * public void schedule(TimerTask task,Date firstTime,long period)
 * 
 * java.util.TimerTask 定时任务
 * public abstract void run() 表示定时任务
 * 
 * 框架Spring里面封装定时器,一般不需要自己手动创建
 */
public class ThreadDemo02 {
	public static void main(String[] args) {
		//创建定时器对象
		Timer timer = new Timer();
		//Timer timer1 = new Timer(true);//后台
		
		//执行任务
		timer.schedule(new LogTimerTask(), new Date(),1000*10);
	}
}
/*
写一个定时任务类:数据备份
*/
class LogTimerTask extends TimerTask{

	@Override
	public void run() {//定时任务
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String strTime = sdf.format(new Date());
		System.out.println(strTime+"成功完成一次数据备份");
		
	}
	
}

生产/消费线程

package com.gxa.demo02;

import java.util.ArrayList;
import java.util.List;

/*
 * 模拟:仓库中有且仅有一个数据
 * 仓库使用List模拟
 * 两个线程:生产,消费
 * 两个线程合作完成,生产一个消费一个
 * 
 * wait()和notify()方法的使用条件
 * 注意:
 * 1.Object中的方法
 * 2.wait()和notify()方法必须由同一个锁对象调用
 * 3.wait()和notify()方法必须使用在同步方法/同步代码块中
 */
public class ConsumerProducerDemo04 {
	public static void main(String[] args) {
		//1.创建共享的仓库对象
		List list = new ArrayList();
		//2.创建两个线程
		Thread t1 = new Thread(new Producer(list));
		Thread t2 = new Thread(new Consumer(list));
		//3.取名
		t1.setName("生产线程");
		t2.setName("消费线程");
		//4.启动
		t1.start();
		t2.start();
	}
}

//生产线程
class Producer implements Runnable{
	//仓库
	private List list;

	
	public Producer(List list) {
		super();
		this.list = list;
	}

	@Override
	public void run() {
		//一直生产(死循环)
		while(true){
			//给仓库加锁
			synchronized (list) {
				if(list.size()>0){//仓库有数据
					//进入等待状态
					try {
						list.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
				//仓库是空的,生产一个数据
				Object obj = new Object();
				list.add(obj);
				System.out.println(Thread.currentThread().getName()+"——生产一个数据"+obj);
				//唤醒消费线程消费
				list.notify();
			}
		}
		
	}
}

//消费线程
class Consumer implements Runnable{

	//仓库
	private List list;
	
	
	public Consumer(List list) {
		super();
		this.list = list;
	}

	@Override
	public void run() {
		//一直消费
		while(true){
			synchronized(list){
				if(list.size()==0){
					//仓库空的,消费线程等待
					try {
						list.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				//仓库中有一个数据,消费
				Object obj = list.remove(0);
				System.out.println(Thread.currentThread().getName()+"——消费一个数据"+obj);
				//唤醒生产线程生产
				list.notify();	
			}
		}
		
	}
	
}

线程池

package com.gxa.demo03;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
 * java.util.concurrent.Executors :
 * public static ExecutorService newFixedThreadPool(int nThreads)参数值为线程数量
 * java.util.concurrent.ExecutorService: 线程池接口
 * Future<?> submit(Runnable task) 执行线程任务
 * 
 * 步骤:
 * 1.创建类实现Runnable,定义线程任务
 * 2.获取线程池,传入线程个数
 * 3.使用线程池的submit()执行任务
 */
public class ThreadPoolDemo01 {
	public static void main(String[] args) {
		//2.获取线程池,传入线程个数
		ExecutorService service = Executors.newFixedThreadPool(2);
        
		//3.使用线程池的submit()执行任务
		MyRunnable mr = new MyRunnable();
		service.submit(mr);
		service.submit(mr);
		service.submit(mr);
		service.submit(mr);
		//void shutdown()
		service.shutdown();
		
	}
}
//1.定义任务
class MyRunnable implements Runnable{

	@Override
	public void run() {
		System.out.println("我要一个美女~~");
		try {
			Thread.sleep(1000*2);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("美女来了:"+Thread.currentThread().getName());
		System.out.println("对我wink~wink~,又回去了");
		
	}
	
}

day8

Lambda

package com.gxa.demo01;
/*
 * 1.Lambda表达式:
 * 格式:(参数)->{代码} 
 * 2.函数式编程思想:注重结果
 * 3.使用前提:
 * 函数式接口(Runnale Comparator)  
 * 作为参数传递
 * 4.作用:简化匿名内部类
 * 5.Lambda表达式省略。简化写法:
 * 1.小括号的参数类型可以省略
 * 2.小括号里面只有一个参数,小括号可以不写
 * 3.大括号里面只有一条语句,无论是否有返回值,
 * 大括号,return,以及分号都可以不写
 */
public class LambdaDemo01 {
	public static void main(String[] args) {
		/*getSum(20,30,(int a,int b)->{
			return a+b;
		});*/
		//简化
		getSum(20,30,(a,b)->a+b);
	}
	 public static void getSum(int a,int b,Sum s){
		 int sum = s.sum(a, b);
		 System.out.println("和为:"+sum);
	 }
}
interface Sum {
	public abstract int sum(int a, int b);
}
package com.gxa.demo02;

public class LambdaDemo02 {
	public static void main(String[] args) {
		getPrint(s->System.out.println(s));
	}
	public static void getPrint(Print p){
		p.print("你好,Lambda");
	}
}
interface Print {
	public abstract int print(String s);
}

常用函数接口

Supplier

T get(); 获取指定泛型类型的数据
package com.gxa.demo03;

import java.util.function.Supplier;

/*
 * 常用的函数式接口1:
 * java.util.function
	Interface Supplier<T>生产接口包含一个无参有返回值的方法:
 	T get(); 获取指定泛型类型的数据
 	
 */
public class FunctionDemo01 {
	public static void main(String[] args) {
		String star = getStar(()->{return "胡歌";});
		System.out.println(star);
	}
	
	public static String getStar(Supplier<String> s){
		return s.get();
	}
}

Consumer消费接口

void accept(T t);
package com.gxa.demo03;

import java.util.function.Consumer;

/*
 * 常用的函数式接口2:
 * java.util.function 
	Interface Consumer<T>消费接口,包含一个有参没有返回值的方法:
	void accept(T t);
 */
public class FunctionDemo02 {
	public static void main(String[] args) {
		setStar((String name)->{
			String s = "你好,"+name;
			System.out.println(s);
		}, "胡歌");
	}
	
	public static void setStar(Consumer<String> c,String name){
		c.accept(name);
	}
}

Predicate 判断/测试接口

boolean test(T t)
package com.gxa.demo03;

import java.util.function.Predicate;

/*
 * java.util.function 
	Interface Predicate<T> 判断/测试接口
 * boolean test(T t)
 */
public class FunctionDemo03 {
	public static void main(String[] args) {
		boolean flag = flag("abcdefgh",(String s)->{return s.length()>4;});
		System.out.println(flag);
	}
	
	public static boolean flag(String str,Predicate<String> p){
		return p.test(str);
	}
}


Function<T,R> 转换功能接口

R apply(T t)
package com.gxa.demo03;

import java.util.function.Function;

/*
 * java.util.function 
	Interface Function<T,R> 转换功能接口
 * R apply(T t)
 */
public class FunctionDemo04 {
	public static void main(String[] args) {
		//converse("1234", (String s)->{return Integer.parseInt(s);});
		converse("1234", s->Integer.parseInt(s));
	}
	
	public static void converse(String s,Function<String, Integer> f){
		Integer i = f.apply(s);
		System.out.println(i);
	}
}

Stream

package com.gxa.demo04;

import java.util.ArrayList;

/*
 * JDK1.8的新特性:函数式接口,Lambda,方法引用,Stream
 * Stream:简化集合/数组操作元素的繁琐
 * 
 * 
 */
public class StreamDemo01 {
	public static void main(String[] args) {
		//武功秘籍
		ArrayList<String> list = new ArrayList<>();
		list.add("九阳神功");
		list.add("九阴白骨jio");
		list.add("一阳指");
		list.add("凌波微步");
		list.add("乾坤大挪移");
		list.add("星宿神功");
		//1.元素长度>=4个
		ArrayList<String> list1 = new ArrayList<>();
		for (String s : list) {
			if(s.length()>=4){
				list1.add(s);
			}
		}
		
		//2.以"jio"结尾
		ArrayList<String> list2 = new ArrayList<>();
		for (String s : list1) {
			if(s.endsWith("jio")){
				list2.add(s);
			}
		}
		
		//3.输出
		System.out.println(list2);
	}
}


package com.gxa.demo04;

import java.util.ArrayList;

public class StreamDemo02 {
	public static void main(String[] args) {
				//武功秘籍
				ArrayList<String> list = new ArrayList<>();
				list.add("九阳神功");
				list.add("九阴白骨jio");
				list.add("一阳指");
				list.add("凌波微步");
				list.add("乾坤大挪移");
				list.add("星宿神功");
				
				//stream:简化
				list.stream()
				.filter(name->name.length()>=4)
				.filter(name->name.endsWith("jio"))
				.forEach(name->System.out.println(name));
	}
}

获取Stream流

package com.gxa.demo04;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Stream;

/*
 * 1.获取Stream流(数组,Collection,Map)
 * Collection获取Stream:default Stream<E> stream()
 * 数组获取Stream:static <T> Stream<T> of(T... values)
 */
public class StreamDemo03 {
	public static void main(String[] args) {
		//1.Collection
		List<String> list = new ArrayList<>();
		Stream<String> stream1 = list.stream();
		
		Set<String> set = new HashSet<>();
		Stream<String> stream2 = list.stream();
		
		//2.数组
		int[] arr = {1,2,3,4,5,6,7};
		Stream<int[]> stream3 = Stream.of(arr);
		
		Stream<Integer> stream4 = Stream.of(1,2,3,4,5);
		
		//3.Map
		Map<String,String> map = new HashMap<>();
		Set<String> keySet = map.keySet();
		Stream<String> stream5 = keySet.stream();
		
		Collection<String> values = map.values();
		Stream<String> stream6 = values.stream();
		
		Set<Entry<String, String>> entrySet = map.entrySet();
		Stream<Entry<String, String>> stream7 = entrySet.stream();
	}
}

forEach遍历流中的数据

package com.gxa.demo04;

import java.util.stream.Stream;

/*
 * Stream:
 * void forEach(Consumer<? super T> action)遍历流中的数据
 * 终止方法:调用forEach()方法,后面就不能在使用Stream中其他的方法
 */
public class StreamDemo04 {
	public static void main(String[] args) {
		//获取Stream
		Stream<String> stream = Stream.of("小红","小橙","小黄","小绿");
		//遍历数据
		//stream.forEach((String name)->{System.out.println(name);});
		stream.forEach(name->System.out.println(name));
	}
}

filter过滤数据

package com.gxa.demo04;

import java.util.stream.Stream;

/*
 * Stream:
 * Stream<T> filter(Predicate<? super T> predicate) 过滤数据
 * 
 */
public class StreamDemo05 {
	public static void main(String[] args) {
		Stream<String> stream = Stream.of("红红","李小红","迪丽热红");
		Stream<String> s = stream.filter(name->name.startsWith("迪丽热"));
		//遍历
		s.forEach(name->System.out.println(name));//迪丽热红
		
		//遍历
		/*
		 * 以下代码报异常:java.lang.IllegalStateException
		 * 第一个流使用完后会关闭,不能再继续使用
		 */
		stream.forEach(name->System.out.println(name));
	}
}

map(Function<? super T,? extends R> mapper) 映射/类型转换

package com.gxa.demo04;

import java.util.stream.Stream;

/*
 * Stream:
 * <R> Stream<R> map(Function<? super T,? extends R> mapper) 映射/类型转换
 * 
 */
public class StreamDemo06 {
	public static void main(String[] args) {
		Stream<String> stream = Stream.of("123","234","345");
		Stream<Integer> stream2 = stream.map(s->Integer.parseInt(s));
		//遍历stream2
		stream2.forEach(name->System.out.println(name));
	}
}


limit(long maxSize) / skip(long n)

package com.gxa.demo04;

import java.util.Arrays;
import java.util.stream.Stream;

/*
 * Stream:
 * Stream<T> limit(long maxSize) 截取数据
 * Stream<T> skip(long n) 跳过数据
 * 
 */
public class StreamDemo07 {
	public static void main(String[] args) {
		String[] arr = {"北京","上海","广州","成都","马栏山"};
		Stream<String> stream = Stream.of(arr);
		//Stream<String> stream2 = Arrays.stream(arr);
		/*Stream<String> stream2 = stream.limit(4);
		stream2.forEach(s->System.out.println(s));*/
		
		Stream<String> stream2 = stream.skip(4);
		stream2.forEach(s->System.out.println(s));
	}
}

count()和foreach()

package com.gxa.demo04;

import java.util.stream.Stream;

/*
 * Stream:
 * static <T> Stream<T> concat(Stream<? extends T> a,Stream<? extends T> b) 连接两个流
 * long count() 流中数据的个数
 * count()和foreach()方法都是终止方法,使用count()后就不能在调用其他的方法了
 */
public class StreamDemo08 {
	public static void main(String[] args) {
		Stream<String> stream1 = Stream.of("喜羊羊","美羊羊","懒羊羊","灰太狼");
		String[] arr = {"水冰月","金星","火星","土星"};
		Stream<String> stream2 = Stream.of(arr);
		//合并
		Stream<String> stream = Stream.concat(stream1, stream2);
		//计算个数
		long l = stream.count();
		System.out.println(l);//8
		//遍历
		stream.forEach(s->System.out.println(s));
	}
}

day 9

IO流

  • 流根据方向可以分为输入流和输出流.
  • 注意:输入输出都是相对于内存,到内存中就输入
  • inputStream/Reader(读数据),
  • OutputStream/Writer(写数据)
  • 一个字符占两个字节

流分类

  1. 按照流向分:输入流和输出流
  2. 按照读取方式:字节流和字符流
  3. 按照处理流方式:字点流和处理流
字节输出流OutputStream-抽象类

定义了子类使用的公有的方法

  1. close()
  2. flush()
  3. void write(byte[] b)
  4. void write(byte[] b,int off,int len)
  5. void write(int b)
FileOutputStream
FileOutputStream(File file)
FileOutputStream(String name)

注意:

  1. 流使用完后要关闭close
  2. 向文件中写入数据,需要刷新flush(), 作用:当缓冲区中没有存满,需要强制刷新并写入.
  3. flush()需要书写在close()方法之前,OutputStream/FileOutStream底层flush()没有具体的实现,你可以==不调用flush();==所以为了保险起见,都去调用刷新方法!!!
package com.gxa.demo01;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/*
 * java.io Class OutputStream:抽象类
 * 定义了供子类使用的公有的方法:
 * 
 * 成员方法:
void write(byte[] b) 将 b.length字节从指定的字节数组写入此输出流。  
void write(byte[] b, int off, int len) 从指定的字节数组写入 len个字节,从偏移 off开始输出到此输出流。  
abstract void write(int b) 将指定的字节写入此输出流。  
void close() 关闭此输出流并释放与此流相关联的任何系统资源。  
void flush() 刷新此输出流并强制任何缓冲的输出字节被写出。  

 * java.io Class FileOutputStream
 * 构造方法:
 * FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。 
 * FileOutputStream(File file) 创建文件输出流以写入由指定的 File对象表示的文件。 
 * 成员方法:
 * 从父类继承过来方法
 * 
 * 注意:
 * 1.流使用完后也需要关闭close()
 * 2.向文件中写入数据需要刷新 flush(),作用:当缓冲区的数据没有存满,强制刷新并写入
 * 3.flush()需要书写在close()方法之前,OutputStream/FileOutStream底层flush()
 * 没有具体的实现,你可以不调用flush。所以为了保险起见,都去调用刷新方法!!!
 */
public class OutputStreamDemo01 {
	public static void main(String[] args) throws IOException {
		//1.创建对象
		FileOutputStream fos  = new FileOutputStream("a.txt");
		
		//2.写数据
		fos.write(97);//a  ASCII编码表 97-a 0-48 A-65
		
		//3.刷新
		fos.flush();
		
		//4.关闭/释放流
		fos.close();
	}
}

package com.gxa.demo01;

import java.io.FileOutputStream;
import java.io.IOException;
/*
 * void write(byte[] b) 将 b.length字节从指定的字节数组写入此输出流。  
void write(byte[] b, int off, int len) 从指定的字节数组写入 len个字节,从偏移 off开始输出到此输出流。  
 */
public class OutputStreamDemo02 {
	public static void main(String[] args) throws IOException {
		FileOutputStream fos = new FileOutputStream("b.txt");
		//byte[] bytes = {65,66,67,68,69};
		/*
		 * void write(byte[] b)
		 * 一次性写入多个字节
		 * 如果写入的第一个字节是正数(0~127),那么显示的ASCII转码后的ABCDEF...
		 * 如果写入的第一个字节是负数,那么第一个和第二个字节两个组成一个中文,那么显示的GBK编码后中文
		 */
		byte[] bytes = {-65,-66,-67,68,69};
		//fos.write(bytes);//ABCDE
		//fos.write(bytes,1,2);//BC
		fos.write(bytes);//烤紻E
		fos.flush();
		fos.close();
	}
}

追加
package com.gxa.demo01;

import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 文件尾部追加写:
 * FileOutputStream(File file, boolean append) 
创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(String name, boolean append) 
创建文件输出流以指定的名称写入文件。 
append
true:不会覆盖原来的文件,继续在文件末尾追加写入
false:覆盖原来的文件

换行:
\r\n windows
/n Linux
/r MAC
 */
public class OutputStreamDemo03 {
	public static void main(String[] args) throws IOException {
		FileOutputStream fos = new FileOutputStream("c.txt",true);
		for (int i = 1; i <=10; i++) {
			fos.write("你好JAVA".getBytes());
			fos.write("\r\n".getBytes());
			fos.flush();
		}
		fos.close();
	}
}

InputStream(读数据)输入流–抽象类

FileInputStream

FileInputStream(File file)

FileInputStream(String name)

int read()
package com.gxa.demo02;

import java.io.FileInputStream;
import java.io.IOException;

/*
 * java.io Class InputStream 抽象类
 * 	abstract int read() 从输入流读取数据的下一个字节。  
	int read(byte[] b) 从输入流读取一些字节数,并将它们存储到缓冲区 b 。  
	int read(byte[] b, int off, int len) 从输入流读取最多 len字节的数据到一个字节数组。  
	void close() 关闭此输入流并释放与流相关联的任何系统资源。 
	
 	java.io.FileInputStream 
 	FileInputStream(String name) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
 	FileInputStream(File file) 通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
 	
 	注意:
 	1.输入流也需要关闭
 	2.读到文件末尾的标致就是-1
 */
public class InpueStreamDemo01 {
	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream("b.txt");//路径存在
	/*	int len = fis.read();
		System.out.println(len);//97
		len = fis.read();
		System.out.println(len);//98
		len = fis.read();
		System.out.println(len);//99
		len = fis.read();
		System.out.println(len);//100
		len = fis.read();
		System.out.println(len);//101
		len = fis.read();
		System.out.println(len);//-1
		len = fis.read();
		System.out.println(len);//-1
*/		
		int len = 0;//记录读取到字节
		while((len=fis.read())!=-1){
			System.out.println(len);
		}
		
		//以下写法是错误的!!!
		/*while(fis.read()!=-1){//97 99 101
			System.out.println(fis.read());//98 100 -1
		}*/
		fis.close();
	}
}

int read(byte[] b)

package com.gxa.demo02;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;

/*
 * 字节输入流一次读取多个字节:
 * int read(byte[] b) 从输入流读取一些字节数,并将它们存储到缓冲区 b。
 * 注意:
 * 1.参数是byte[]的作用?
 * 缓冲的作用,存储每次读取到的多个字节
 * 此缓冲数组长度一搬定义为1024或者1024的整数倍
 * 2.返回值int是什么?
 * 每次读取到的有效字节数量
 */
public class InputStreamDemo02 {
	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream("b.txt");//路径存在
		/*byte[] bytes = new byte[2];
		int len = fis.read(bytes);
		System.out.println(len);//2 每次读取到的有效字节数量
		System.out.println(Arrays.toString(bytes));//[97, 98]
		len = fis.read(bytes);
		System.out.println(len);//2 每次读取到的有效字节数量
		System.out.println(Arrays.toString(bytes));//[99, 100]
		len = fis.read(bytes);
		System.out.println(len);//1 每次读取到的有效字节数量
		System.out.println(Arrays.toString(bytes));//[101, 100]
		len = fis.read(bytes);
		System.out.println(len);//-1 每次读取到的有效字节数量
		System.out.println(Arrays.toString(bytes));//[101, 100]
*/		
		
		//优化以上读取方式
		byte[] bytes = new byte[1024];//存储读取的字节
		int len = 0;//记录每次读取到的有效字节数量
		while((len=fis.read(bytes))!=-1){
			System.out.println(new String(bytes, 0, len));//abcde
		}
		fis.close();
		
	}
}

图片读写

package com.gxa.demo02;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * FileInputStream/FileOutputStream
 * 读写二进制文件(图片,视频,音频)
 * 复制粘贴:
 * 1.先读图片 D:\\cloud\\1.jpg
 * 2.再写入到D:\\1.jpg
 */
public class File01 {
	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream("D:\\cloud\\1.jpg");
		FileOutputStream fos = new FileOutputStream("D:\\1.jpg");
		byte[] bytes = new byte[1024];
		int len = 0;
		while((len=fis.read(bytes))!=-1){
			fos.write(bytes, 0, len);
		}
		fos.flush();
		fis.close();
		fos.close();
	}
}

字符流

Reader抽象类

文件字符输入流FileReader

package com.gxa.demo02;

import java.io.FileInputStream;
import java.io.IOException;
/*
 * 使用字节输入流一个字节一个字节读取含有中文的文件:会出现读取到不完整字符的文字!!
 * 1个中文
 * GBK: 占2个字节 UTF:3个字节
 */
public class InputStreamDemo03 {
	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream("c.txt");
		int len = 0;
		while((len=fis.read())!=-1){
			System.out.println((char)len);//??°??ú
		}
		fis.close();
	}
}

Reader

package com.gxa.demo03;

import java.io.FileReader;
import java.io.IOException;

/*
 * java.io Class Reader 抽象类,字符输入流
 * 	int read() 读一个字符  
	int read(char[] cbuf) 将字符读入数组。  
	abstract int read(char[] cbuf, int off, int len) 将字符读入数组的一部分。  
	public abstract void close()throws IOException关闭流并释放与之相关联的任何系统资源。
	
	java.io.Reader 
		java.io.InputStreamReader 
			java.io.FileReader 文件字符输入流
	适合读含有中文的纯文本文件
	构造方法:
	FileReader(String fileName) 创建一个新的 FileReader ,给定要读取的文件的名称。 
	成员方法:
	从父类继承过来的
 */
public class ReaderDemo01 {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("c.txt");
		/*int len = 0;
		while((len=fr.read())!=-1){
			System.out.println((char)len);
		}*/
		char[] ch = new char[1024];
		int len = 0;
		while((len=fr.read(ch))!=-1){
			System.out.println(new String(ch, 0, len));
		}
		
		fr.close();
	}
}

Writer

package com.gxa.demo03;

import java.io.FileWriter;
import java.io.IOException;

/*
 * java.io.Writer 
	java.io.OutputStreamWriter 
		java.io.FileWriter 文件字符输出流
	构造方法:
	FileWriter(String fileName) 构造一个给定文件名的FileWriter对象。  
	FileWriter(String fileName, boolean append) 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。  

	成员方法:
	void write(char[] cbuf) 写入一个字符数组。  
	abstract void write(char[] cbuf, int off, int len) 写入字符数组的一部分。  
	void write(int c) 写一个字符  
	void write(String str) 写一个字符串  
	void write(String str, int off, int len) 写一个字符串的一部分。  
	public abstract void flush()throws IOException刷新流。
	public abstract void close()throws IOException关闭流,先刷新。
	
	注意:
	1.记得关闭close流
	2.直接写入字符串
	3.记得flush刷新
 */
public class WriterDemo01 {
	public static void main(String[] args) throws IOException {
		FileWriter fw = new FileWriter("d.txt",false);
		fw.write(97);
		char[] ch = {'a','b','c','d','e'};
		fw.write(ch);
		fw.write(ch,1,3);
		fw.write("迪丽热巴");
		fw.flush();
		fw.close();
	}
}

关闭流

package com.gxa.demo04;

import java.io.FileWriter;
import java.io.IOException;

/*
 * close() 和 flush()
 * flush:刷新缓冲区,流可以继续使用
 * close:先刷新再通知系统释放流空间。流不可以再使用
 */
public class CloseFlushDemo01 {
	public static void main(String[] args) throws IOException {
		FileWriter fw = new FileWriter("e.txt");
		fw.write(97);
		fw.flush();
		fw.write("abc");
		fw.flush();
		fw.close();
		fw.write(98);//java.io.IOException: Stream closed 报异常
	}
}

1.7版本以后,try (){}

package com.gxa.demo04;

import java.io.FileWriter;
import java.io.IOException;

/*
 * 处理流中的异常方式一:jdk1.7之前
 * try{
 * 	出现异常的代码
 * }catch(异常){
 * 	e.printStackTrace()
 * }finally{//一定会执行
 * 	 释放流资源
 * }
 */
public class TryCatchDemo02 {
	public static void main(String[] args) {
		FileWriter fw = null;
		try{
			fw = new FileWriter("d.txt",false);
			fw.write(97);
			char[] ch = {'a','b','c','d','e'};
			fw.write(ch);
			fw.write(ch,1,3);
			fw.write("迪丽热巴");
			fw.flush();
		}catch(IOException e){
			e.printStackTrace();
		}finally{
			if(fw!=null){
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
}

package com.gxa.demo04;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 处理流中的异常方式二:jdk1.7之后
 * 格式:
 * try(定义的流对象;定义流对象;){
 * 	出现异常的代码
 * }catch(异常){
 * 	  e.printStackTrace()
 * }
 * (定义的流对象;定义流对象;),在小括号中定义的流,在try代码块中可以使用,使用完毕后会
 * 自动释放流资源,所以无需加finally{}
 */
public class TryCatchDemo03 {
	public static void main(String[] args) {
		try(FileInputStream fis = new FileInputStream("D:\\cloud\\1.jpg");
			FileOutputStream fos = new FileOutputStream("D:\\1.jpg");){
			byte[] bytes = new byte[1024];
			int len = 0;
			while((len=fis.read(bytes))!=-1){
				fos.write(bytes, 0, len);
			}
			fos.flush();
		}catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

Properties

package com.gxa.demo05;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;

/*
 * java.util.Properties 
 * 1.线程安全集合
 * 2.唯一一个和IO流有关的双列集合
 * 3.key和value只能存储String
 * 
 * 成员方法:
 *  public Object setProperty(String key,String value)存储数据
 *  public String getProperty(String key) 根据key取出值
 *  void load(InputStream inStream) 从输入字节流读取属性列表(键和元素对)。  
	void load(Reader reader) 以简单的线性格式从输入字符流读取属性列表(关键字和元素对)。  
	void store(OutputStream out, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法加载到 Properties表中的格式输出流。  
	void store(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式输出到输出字符流。  
	public Set<String> stringPropertyNames() 遍历集合
	
	注意:
	1.#内容是注释掉的内容,注释内容不会读取到并输出的
 */
public class PropertiesDemo01 {
	public static void main(String[] args) throws IOException {
		Properties prop = new Properties();
		/*prop.setProperty("鹿晗", "小鹿");
		prop.setProperty("张艺兴", "小绵羊");
		prop.setProperty("黄子韬", "小熊猫");
		prop.setProperty("吴亦凡", "小牙签");*/
		//写入数据到文件中
		//prop.store(new FileWriter("prop.txt"), "flower4");
		//读取文件中的数据
		prop.load(new FileReader("prop.txt"));
		
		Set<String> set = prop.stringPropertyNames();
		for (String key : set) {
			String value = prop.getProperty(key);
			System.out.println(key+"="+value);
		}
	}
}

BufferedReader

package com.gxa.demo06;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/*
 * java.io Class Reader 抽象类,字符输入流
 * 	int read() 读一个字符  
	int read(char[] cbuf) 将字符读入数组。  
	abstract int read(char[] cbuf, int off, int len) 将字符读入数组的一部分。  
	public abstract void close()throws IOException关闭流并释放与之相关联的任何系统资源。
	
	java.io.Reader 
		java.io.BufferedReader 缓冲字符输入流
	构造方法:
	BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。  
	BufferedReader(Reader in, int sz) 创建使用指定大小的输入缓冲区的缓冲字符输入流。  

	成员方法:
	从父类Reader继承有关读,关闭流的方法
	public String readLine()throws IOException 读一行文字
 */
public class BufferedReaderDemo01 {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new FileReader("c.txt"));
		String line;//读取到一行内容
		while((line=br.readLine())!=null){
			System.out.println(line);
		}
		br.close();
	}
}

BufferedWriter

package com.gxa.demo06;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/*
 * java.io.Writer 
		java.io.BufferedWriter 
	成员方法:
	BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。  
	BufferedWriter(Writer out, int sz) 创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。

  	成员方法:
  	void write(char[] cbuf) 写入一个字符数组。  
	abstract void write(char[] cbuf, int off, int len) 写入字符数组的一部分。  
	void write(int c) 写一个字符  
	void write(String str) 写一个字符串  
	void write(String str, int off, int len) 写一个字符串的一部分。  
	public abstract void flush()throws IOException刷新流。
	public abstract void close()throws IOException关闭流,先刷新。
	public void newLine()throws IOException写一行行分隔符。

 */
public class BufferedWriterDemo01 {
	public static void main(String[] args) throws IOException {
		BufferedWriter bw = new BufferedWriter(new FileWriter("f.txt"));
		for (int i = 0; i < 10; i++) {
			bw.write("你好JAVA");
			bw.newLine();//换行
		}
		bw.flush();
		bw.close();
	}
}

day10

FileReader

package com.gxa.demo01;

import java.io.FileReader;
import java.io.IOException;

/*
 * FileReader读取UTF-8编码的文件utf8.txt
 * 产生乱码:
 * 锘挎垜鏄竴涓
 */
public class FileReaderDemo01 {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("utf8.txt");
		int len = 0;
		while((len=fr.read())!=-1){
			System.out.println((char)len);
		}
		fr.close();
	}
}

InputStreamReader 转换流-设置编码

package com.gxa.demo01;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/*
 * java.io.Reader 
		java.io.InputStreamReader 转换流-设置编码
	构造方法:
	public InputStreamReader(InputStream in,String charsetName)throws UnsupportedEncodingException
	
	charsetName-字符集编码:utf-8/UTF-8 gbk/GBK
	
 */
public class InputStreamReaderDemo01 {
	public static void main(String[] args) throws IOException {
		InputStreamReader isr = new InputStreamReader(new FileInputStream("utf8.txt"),"utf-8");
		int len = 0;
		while((len=isr.read())!=-1){
			System.out.println((char)len);
		}
		isr.close();
	}
}

OutputStreamWriter 转换流-设置编码

package com.gxa.demo01;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/*
 * java.io.Writer 		
		java.io.OutputStreamWriter 转换流-设置编码
	构造方法:
	OutputStreamWriter(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter。 
	
	
 */
public class OutputStreamWriterDemo01 {
	public static void main(String[] args) throws IOException {
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf-8.txt"),"utf-8");
		osw.write("UTF8文件");
		osw.flush();
		osw.close();
	}
}

Serializable

package com.gxa.demo02;

import java.io.Serializable;

/*
 * 没有实现接口报以下异常: java.io.NotSerializableException: com.gxa.demo02.Person
 * 没有添加序列化版本号报以下异常:当Person类有所改动,再反序列化时出现异常
 * java.io.InvalidClassException: com.gxa.demo02.Person; 
 * local class incompatible: 
 * stream classdesc serialVersionUID = -5732364256307530591, 
 * local class serialVersionUID = 7196992608609903554
	
 * 序列化有条件:
 * 1.Person实体类实现Serializable可序列化接口
 * 2.添加序列化版本号
 */
public class Person implements Serializable{
	/**
	 * 序列化版本号:类唯一标识
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	private String hobby;
	private int 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 getHobby() {
		return hobby;
	}
	public void setHobby(String hobby) {
		this.hobby = hobby;
	}
	public int getSex() {
		return sex;
	}
	public void setSex(int sex) {
		this.sex = sex;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", hobby=" + hobby + ", sex=" + sex + "]";
	}
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	
	
	
}

ObjectOutputStream 序列化

package com.gxa.demo02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/*
 * 序列化:把对象写入到文件中
 * java.io.ObjectOutputStream 
 * 
 * 构造方法:
 * public ObjectOutputStream(OutputStream out) throws IOException
 * 
 * 成员方法:
 * public final void writeObject(Object obj)throws IOException将指定的对象写入ObjectOutputStream
 */
public class ObjectOutputStreamDemo01 {
	public static void main(String[] args) throws IOException {
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("p.txt"));
		oos.writeObject(new Person("易烊千玺", 22));
		oos.flush();
		oos.close();
	}
}

ObjectInputStream反序列化

package com.gxa.demo02;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/*
 * 反序列化:读取文件中的对象
 * ObjectInputStream
 * 构造方法:
 * public ObjectInputStream(InputStream in) throws IOException
 * 成员方法:
 * public final Object readObject()throws IOException,ClassNotFoundException从ObjectInputStream读取一个对象
 */
public class ObjectInputStreamDemo01 {
	public static void main(String[] args) throws ClassNotFoundException, IOException {
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("p.txt"));
		Object obj = ois.readObject();
		Person p = (Person)obj;
		System.out.println(p);//Person [name=易烊千玺, age=22]
		ois.close();
	}
}

PrintStream 打印流

package com.gxa.demo03;

import java.io.FileNotFoundException;
import java.io.PrintStream;

/*
 * java.io.OutputStream 
		java.io.FilterOutputStream 
			java.io.PrintStream 打印流
	1.只负责输出数据,不负责输入数据
	2.其他的流处理IOException异常,PrintStream不是
	3.除了继承/重写自父类write()还有特有的print()/println()方法,负责输出数据
	write方法写入的数据通过ASCII编码,print()/println()不会通过ASCII编码,写入什么就是什么
	构造方法:
	public PrintStream(OutputStream out)
	public PrintStream(String s)
	成员方法:
	void print(Object obj) 打印一个对象。  
	void print(String s) 打印字符串。 
	void println(boolean x) 打印一个布尔值,然后终止该行。  
	void println(char x) 打印一个字符,然后终止该行。 
	void write(byte[] buf, int off, int len) 从指定的字节数组写入 len个字节,从偏移 off开始到此流。  
	void write(int b) 将指定的字节写入此流。  


 */
public class PrintStreamDemo01 {
	public static void main(String[] args) throws FileNotFoundException {
		PrintStream ps = new PrintStream("print.txt");
		ps.write(98);
		ps.print(99);
		ps.println(false);
		ps.print(3.14);
		ps.close();
	}
}

package com.gxa.demo03;

import java.io.FileNotFoundException;
import java.io.PrintStream;

/*
 * java.io.OutputStream 
		java.io.FilterOutputStream 
			java.io.PrintStream 打印流
	1.只负责输出数据,不负责输入数据
	2.其他的流处理IOException异常,PrintStream不是
	3.除了继承/重写自父类write()还有特有的print()/println()方法,负责输出数据
	write方法写入的数据通过ASCII编码,print()/println()不会通过ASCII编码,写入什么就是什么
	构造方法:
	public PrintStream(OutputStream out)
	public PrintStream(String s)
	成员方法:
	void print(Object obj) 打印一个对象。  
	void print(String s) 打印字符串。 
	void println(boolean x) 打印一个布尔值,然后终止该行。  
	void println(char x) 打印一个字符,然后终止该行。 
	void write(byte[] buf, int off, int len) 从指定的字节数组写入 len个字节,从偏移 off开始到此流。  
	void write(int b) 将指定的字节写入此流。  

	System类:
	public static void setOut(PrintStream out)重新分配“标准”输出流。 

 */
public class PrintStreamDemo01 {
	public static void main(String[] args) throws FileNotFoundException {
		PrintStream ps = new PrintStream("print.txt");
		//写入到文件中
		ps.write(98);
		ps.print(99);
		ps.println(false);
		ps.print(3.14);
		System.setOut(ps);//重新分配流的流向
		System.out.println("哈哈哈");
		//刷新
		ps.flush();
		ps.close();
	}
}

DataOutputStream:数据流

package com.gxa.demo03;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * DataOutputStream:数据流
 * 构造方法:
 * public DataOutputStream(OutputStream out)
 * 成员方法:
 * 	void writeBoolean(boolean v) 将 boolean写入底层输出流作为1字节值。  
	void writeByte(int v) 将 byte作为1字节值写入底层输出流。  
	void writeBytes(String s) 将字符串作为字节序列写入基础输出流。  
	void writeChar(int v) 将 char写入底层输出流作为2字节值,高字节优先。 
	
	注意:
	1.写入文件的数据为二进制数组,打开文件就是一堆乱码
 */
public class DataOutputStreamDemo01 {
	public static void main(String[] args) {
		DataOutputStream dos = null;
		try {
			FileOutputStream fos = new FileOutputStream("a.txt");
			BufferedOutputStream bos = new BufferedOutputStream(fos);
			dos = new DataOutputStream(bos);
			//写入数据
			dos.writeInt(20);
			dos.writeDouble(123.45);
			dos.writeBoolean(false);
			dos.writeUTF("gxan");
			//刷新
			dos.flush();
		}catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(dos!=null){
				//释放流
				try {
					dos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

package com.gxa.demo03;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * java.io.InputStream 
		java.io.FilterInputStream 
			java.io.DataInputStream :数据流
	public DataInputStream(InputStream in)
	char readChar() 见 readChar方法的总合同 DataInput 。  
	double readDouble() 见 readDouble方法 DataInput的总体合同。  
	float readFloat()  

	注意:
	1.使用DataOutputStream写入的数据,必须通过DataInputStream读
	2.读数据和写数据的顺序要一致
 */
public class DataInputStreamDemo01 {
	public static void main(String[] args) {
		DataInputStream dis = null;
		try {
			FileInputStream fis = new FileInputStream("a.txt");
			BufferedInputStream bis = new BufferedInputStream(fis);
			dis = new DataInputStream(bis);
			//读数据
			int i = dis.readInt();
			double d = dis.readDouble();
			boolean b = dis.readBoolean();
			String utf = dis.readUTF();
			System.out.println(i+"-"+d+"-"+utf+"-"+b);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(dis!=null){
				try {
					dis.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
}

网络编程

package com.gxa.demo04;

import java.net.InetAddress;
import java.net.UnknownHostException;

/*
 * 牛客APP——JAVA——笔试题——晨会分享
 * MYSQL先不用自己安装,也不用卸载,mysql5.7
 * 
 * 网络编程:——为后面安装服务器Tomcat做准备
 * 1.软件架构:
 * B/S架构:全称Broswer/Server 浏览器/服务器结构
 * C/S架构:全称Client/Server 客户端/服务器结构
 * 2.网络编程:
 * 软件架构是有两种,无论使用哪种都离不开网络
 * 网络编程就是在一定的协议下,实现两台计算机交流
 * 3.网络编程三要素:通信协议,端口号,IP地址——重要!!!
 * 3.1通信协议:是计算机必须遵守的规则,只有遵守这些规则计算机之间才可以交流
 * 协议中主要对传输的数据的传输格式,传输速率,传输标准做了规范,通信双方都要遵守,最后完成数据交流
 * 3.2常见的通信协议——重要!!!
 * TCP(Transfer Control Protocol):传输控制协议
 * 七层(5/4层):
 * 	应用层:网络服务与最终用户的一个接口。
	表示层:数据的表示、安全、压缩。
	会话层:建立、管理、终止会话。
	传输层:定义传输数据的协议端口号,以及流控和差错校验。
	网络层:进行逻辑地址寻址,实现不同网络之间的路径选择。
	数据链路层:建立逻辑连接、进行硬件地址寻址、差错校验等功能。
	物理层:建立、维护、断开物理连接。
	特点:面向连接的点对点协议,可靠无差错传输数据,安全(原因:三次握手和四次挥手-面试),效率低
 	例如:何靖打电话给迪丽热巴表白
 * UDP(User Datagram Protocol)用户数据报协议
 * 特点:面向无连接的协议,不安全,效率高
 * 例如:QQ的漂流瓶
 * HTTP——后面三阶段Servlet
 * 
 * 4.IP地址
 * 互联网协议地址,用来给网络中的设备做编号
 * IPV4 IPV6(网络地址资源不够)
 * 查看:ipconfig
 * 
 * 特殊:localhost/127.0.0.1 本机回还地址
 * 
 * 5.端口号
 * 计算机中每一个应用程序都会分配一个端口号(QQ:300 微信:400 企业微信:500)
 * 每台计算机都有很多进程,在网络通信中使用端口号区分
 * 0~65535取值范围
 * 
 * 特殊:常用端口 mysql-3306 Orcale-1521 Tomcat服务器-8080
 * 
 * 6.用代码模拟客户端和服务器之间的通信(TCP/UDP)
 * 
 * 7.IP地址封装类:InetAddress
 * 	public static InetAddress getLocalHost() 获取本地主机相关信息
 * 	String getHostAddress() 返回文本显示中的IP地址字符串。  
	String getHostName() 获取此IP地址的主机名。  
	static InetAddress[] getAllByName(String host) 给定主机的名称,根据系统上配置的名称服务返回其IP地址数组。 

 */
public class InetAdrressDemo01 {
	public static void main(String[] args) throws UnknownHostException {
		//1.获取本地主机相关信息
		InetAddress ia = InetAddress.getLocalHost();
		//2.获取本地IPV4地址
		System.out.println(ia.getHostAddress());//192.168.227.73
		//3.获取本地主机名
		System.out.println(ia.getHostName());//DESKTOP-GQANJVM
		//4.获取主机的IPV4地址——DESKTOP-GQANJVM
		System.out.println(InetAddress.getByName("DESKTOP-GQANJVM").getHostAddress());//192.168.227.73
		//5.获取所有的IP地址
		InetAddress[] ias = InetAddress.getAllByName("DESKTOP-GQANJVM");
		for (InetAddress i : ias) {
			System.out.println(i.getHostAddress());
		}
	}
}

package com.gxa.demo04;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/*
 * TCP客户端:Socket
 * 步骤: 向服务器发送请求,给服务器传送数据,读取服务器回写的数据
 * public Socket(String host,int port)
 * public InputStream getInputStream()throws IOException返回此套接字的输入流。
	public OutputStream getOutputStream()throws IOException返回此套接字的输出流。
 */
public class TCPClient {
	public static void main(String[] args) throws IOException {
		//1.创建Socket对象
		Socket socket = new Socket("127.0.0.1", 8888);
		//2.给服务器写数据
		OutputStream os = socket.getOutputStream();
		os.write("你好鸭,服务器".getBytes());
		//3.读取服务器回写的数据
		InputStream is = socket.getInputStream();
		byte[] bytes = new byte[1024];
		int len = is.read(bytes);
		System.out.println(new String(bytes,0,len));
		//4.释放资源
		socket.close();
	}
}

package com.gxa.demo04;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * TCP服务器端:ServerSocket-不能关闭
 * 步骤;
 * 接收客户端请求,读取客户端数据,给客户端回写数据
 * public ServerSocket(int port)throws IOException创建绑定到指定端口的服务器套接字
 * public Socket accept()throws IOException侦听要连接到此套接字并接受它。
 */
public class TCPServer {
	public static void main(String[] args) throws IOException {
		//1.创建对象
		ServerSocket ss = new ServerSocket(8888);
		//2.接收客户端请求
		Socket socket = ss.accept();
		//3.读取客户端数据
		InputStream is = socket.getInputStream();
		byte[] bytes = new byte[1024];
		int len = is.read(bytes);
		System.out.println(new String(bytes,0,len));
		//4.给客户端回写数据
		OutputStream os = socket.getOutputStream();
		os.write("收到,思密达".getBytes());
		//5.释放资源
		socket.close();
	}
}

day 11

反射

UDP客户端:发送数据

package com.gxa.demo01;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/*
 * UDP客户端:发送数据
 * java.net.DatagramSocket 
 * 1.创建DatagramSocket对象
 * public DatagramSocket()throws SocketException
 * 2.定义发送的数据 HelloUDP
 * 3.创建发送的数据的包对象:java.net.DatagramPacket  指定IP和端口号
 * public DatagramPacket(byte[] buf,int offset,int length,InetAddress address,int port)
 * 4.发送数据报包:
 * public void send(DatagramPacket p) throws IOException从此套接字发送数据报包
 */
public class UDPClient {
	public static void main(String[] args) {
		try {
			DatagramSocket socket = new DatagramSocket();
			String s = "HelloUDP";
			byte[] bytes = s.getBytes();
			DatagramPacket pck = new DatagramPacket(bytes, 0, bytes.length, InetAddress.getLocalHost(),3456);
			socket.send(pck);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

UDP服务器:

package com.gxa.demo01;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/*
 * UDP服务器:
 * java.net.DatagramSocket 
 * 1.创建DatagramSocket对象
 * public DatagramSocket(int port)throws SocketException
 * 2.接收客户端发送的数据报包
 * public void receive(DatagramPacket p)throws IOException从此套接字接收数据报包。
 * 3.输出数据
 * java.net.DatagramPacket
 * 	byte[] getData() 返回数据缓冲区。  
	int getLength() 返回要发送的数据的长度或接收到的数据的长度。  
	int getOffset() 返回要发送的数据的偏移量或接收到的数据的偏移量。  

 */
public class UDPServer {
	public static void main(String[] args) throws Exception {
		DatagramSocket socket = new DatagramSocket(3456);
		byte[] data = new byte[16];
		DatagramPacket pck = new DatagramPacket(data, 0,data.length);
		socket.receive(pck);
		String str = new String(pck.getData(), pck.getOffset(), pck.getLength());
		System.out.println(str);
	}
}

获取Class类对象方式

package com.gxa.demo02;
/*
 * 1.获取Class类对象方式:
 * 1.1 Class.forName("全类名") 全类名=包名.类名
 * Class类中:
 * public static 类<?> forName(String className)throws ClassNotFoundException
 * 1.2 类名.class
 * 1.3 对象名.getClass()
 * Object类中 public final 类<?> getClass()
 */
public class ReflectionDemo01 {
	public static void main(String[] args) throws ClassNotFoundException {
		//1.Class.forName("全类名")
		Class cls1 = Class.forName("com.gxa.demo02.Person");
		System.out.println(cls1);//class com.gxa.demo02.Person
		//2.类名.class
		Class cls2 = Person.class;
		System.out.println(cls2);//class com.gxa.demo02.Person
		
		//3.对象名.getClass()
		Person p = new Person();
		Class cls3 = p.getClass();
		System.out.println(cls3);//class com.gxa.demo02.Person
		
		System.out.println(cls1==cls2);//true
		System.out.println(cls3==cls2);//true
	}
}

package com.gxa.demo02;
//实体类
public class Person {
	//成员变量
	private String name;
	private int age;
	
	
	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;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	//构造方法
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	//成员方法
	
	public void sleep(){
		System.out.println("睡睡睡");
	}
	
	public void sleep(String s){
		System.out.println("睡"+s);
	}
	
}

Class:获取成员变量们

package com.gxa.demo02;

import java.lang.reflect.Field;

/*
 * Class:获取成员变量们
 * 	Field getField(String name) 返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段 类对象。  
	Field[] getFields() 返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段 类对象 
	Field getDeclaredField(String name) 返回一个 Field对象,它反映此表示的类或接口的指定已声明字段 类对象。  
	Field[] getDeclaredFields() 返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象。 
	Field:为成员变量赋值/取出值
	void set(Object obj, Object value) 将指定对象参数上的此 Field对象表示的字段设置为指定的新值。  
	public Object get(Object obj)throws IllegalArgumentException,IllegalAccessException返回该所表示的字段的值Field 
	注意:
	getField(String name)和getFields()只能获取到public修饰的成员变量

 */
public class ReflectionDemo02 {
	public static void main(String[] args) throws Exception{
		//1.获取类对象Class
		Class cls = Person.class;
		//2.获取成员变量
		//2.1获取public修饰成员变量
		Field[] fields = cls.getFields();
		for (Field field : fields) {
			System.out.println(field);
		}
		//2.2获取某一个public修饰成员变量
		Field a = cls.getField("a");
		//2.3赋值
		Person p = new Person();
		a.set(p,true);
		//2.4取值
		Object o = a.get(p);
		System.out.println(o);//true
		
		//3.获取所有的成员变量,不考虑修饰符
		Field[] declaredFields = cls.getDeclaredFields();
		for (Field declaredfield : declaredFields) {
			System.out.println(declaredfield);
		}
		
		Field name = cls.getDeclaredField("name");
		//如果成员变量是private修饰,加暴力反射
		name.setAccessible(true);
		name.set(p, "zhangsan");
		System.out.println(name.get(p));
	}
}

Class:获取构造方法们

package com.gxa.demo02;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/*
 * Class:获取构造方法们
 * 	Constructor<T> getConstructor(类<?>... parameterTypes) 返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。  
	Constructor<?>[] getConstructors() 返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 类对象。  
	Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) 返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。  
	Constructor<?>[] getDeclaredConstructors() 返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 类 。  
	java.lang.reflect.Constructor<T> 类中
	public T newInstance(Object... initargs)创建对象时为成员变量赋值

 */
public class ReflectionDemo03 {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		//1.获取Class类对象
		Class cls = Person.class;
		
		//2.获取有参构造方法
		Constructor constructor = cls.getConstructor(String.class,int.class);
		System.out.println(constructor);//public com.gxa.demo02.Person(java.lang.String,int)
		//3.创建对象
		Object person = constructor.newInstance("lisi",33);
		System.out.println(person);//Person [name=lisi, age=33]
		
		//3.获取无参构造方法
		Constructor constructor2 = cls.getConstructor();
		System.out.println(constructor2);//public com.gxa.demo02.Person()
		Object person2 = constructor2.newInstance();
		System.out.println(person2);//Person [name=null, age=0]
	}
}

Class:获取成员方法们

package com.gxa.demo02;

import java.lang.reflect.Method;

/*
 * Class:获取成员方法们
 * 	方法 getMethod(String name, 类<?>... parameterTypes) 返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 类对象。  
	方法[] getMethods() 返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。  
	方法 getDeclaredMethod(String name, 类<?>... parameterTypes) 返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 类对象。  
	方法[] getDeclaredMethods() 返回包含一个数组 方法对象反射的类或接口的所有声明的方法 
	java.lang.reflect.Method 
	public Object invoke(Object obj,Object... args)在具有指定参数的方法对象上调用此方法对象表示的基础方法。
 */
public class ReflectionDemo04 {
	public static void main(String[] args) throws Exception, SecurityException {
		//1.获取Class类对象
		Class cls = Person.class;
		//2.获取无参的成员方法
		Method method1 = cls.getMethod("sleep");
		Person p = new Person();
		method1.invoke(p);//睡睡睡
		//3.获取有参的成员方法
		Method method2 = cls.getMethod("sleep", String.class);
		method2.invoke(p,"一万年");//睡一万年
		
		
		
	}
}

类加载器ClassLoader

package com.gxa.demo03;
/*
 * 类加载器ClassLoader:
 * 1.类加载器就是负责加载类的工具
 * 2.Class类:public ClassLoader getClassLoader()返回类的类加载器。
 * 3.JDK中有3个自定义类加载器
 * 启动(引导)类加载器(父加载器) 扩展类加载器(母加载器) 应用(系统)类加载器
 * D:\jdk1.8.0_121\jre\lib\rt.jar
 * D:\jdk1.8.0_121\jre\lib\ext\*.jar
 * 配置环境变量中路径
 * 4.双亲委派机制
 * 优先从父找,再从母找,都找不到去找应用类加载器
 * 5.java.lang Class ClassLoader
 * public InputStream getResourceAsStream(String name)返回用于读取指定资源的输入流。
 * 结合Properties一起读取 .properties的配置文件
 */
public class ClassLoaderDemo01 {
	public static void main(String[] args) {
		
	}
}

注解

package com.gxa.demo05;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/*
 * 注解的使用:
 * 注解在框架中使用时,替换配置文件,替换时用到反射
 * Class:
 * public Annotation[] getAnnotations() 获取所有的注解
 * public boolean isAnnotationPresent(类<? extends Annotation> annotationClass)如果此元素上存在指定类型的注释
 * 
 * 
 */
@Pro(className="com.gxa.demo05.Person",methodName="sleep")
public class AnnotationFrame {
	public static void main(String[] args) throws Exception {
		//1.获取类对象
		Class<AnnotationFrame> cls = AnnotationFrame.class;
		//2.获取注解
		Pro pro = cls.getAnnotation(Pro.class);
		//3.调用注解属性名获取属性值
		String className = pro.className();
		String methodName = pro.methodName();
		
		//3.加载进内存
		Class cls1 = Class.forName(className);//Person/Teacher类对象
				
		//4.创建对象
		Object obj = cls1.newInstance();
				
		//5.获取方法
		Method method = cls1.getMethod(methodName);
				
		//6.执行方法
		method.invoke(obj);
	}
}

className=com.gxa.demo03.Teacher
methodName=teach
package com.gxa.demo04;

/*
 * 1.注解的概念:说明程序给计算机看
 * 注解是JDK1.5的新特性,和类,接口,枚举
 * 2.注解:
 * A)自定义: @interface声明一个注解
 * 在注解里面定义属性
 * 
 * 定义了属性,在使用时需要给属性赋值
 * 2.1如果定义属性使用default关键字给了默认初始值,那么使用时不用赋值
 * 2.2如果只有一个属性,属性名value,那么value可以省略,直接定义值
 * 2.3数组赋值时,值使用{}花括号包裹,如果数组中只有一个值,那么{}可以省略不写
 * 
 * B)预定义:
 * @Override @FunctionalInterface @SuppressWarnings("all") @Deprecated已过时
 * 
 * C)元注解(注解上方定义的注解):约束注解
 * 	@Documented 表示能否被抽取到API文档中
	@Retention(RetentionPolicy.RUNTIME)表示的是注解可以保留到哪个阶段(Source Class Runtime)
	@Target(ElementType.TYPE)表示的是该注解可以放在哪里(类)
	public @interface FunctionalInterface {}
	
	
	@Documented
	@Retention(RetentionPolicy.RUNTIME)
	表示的是该注解可以放在哪里(构造方法,属性,变量,成员方法,包,方法参数,类)
	@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
	public @interface Deprecated {
	}
 */
public @interface Anno {
	int value();//属性
	String s();
	Person p();
	//String[] strs();//属性
}

package com.gxa.demo05;
//实体类
public class Person {
	//成员变量
	private String name;
	private int age;
	
	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;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	//构造方法
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	//成员方法
	
	public void sleep(){
		System.out.println("睡睡睡");
	}
	
	public void sleep(String s){
		System.out.println("睡"+s);
	}

}

数据库

DDL

DDL创建数据库

create database if not exists mydb;

create database mydb;

查看所有的数据库

show databases;

删除数据库

drop database if exists mydb1;

查看数据库创建的语句

show create database mydb

修改数据库的字符集编码

alter database mydb character set gbk;

使用库:创建表时,一定要使用库!!!

use mydb;

查看正在使用的数据库

select database();

查看数据库有哪些表

show tables;

查看数据库版本

select version() from dual

utf8 和 utf8mb4区别?

UTF8字符集一个汉字占据3个字符

UTF8MB4字符集一个汉字占据4个字符,一些特殊字符和emoji表情需要

数据类型:

分类类型名称类型说明
整型tinyint微整型:很小的整数(占 8 位二进制)
samllint小整型:小的整数(占 16 位二进制)
mediumint中整型:中等长度的整数(占 24 位二进制)
int(integer)整型:整数类型(占 32 位二进制)
小数float单精度浮点数,占 4 个字节
double(m,d)双精度浮点数,占 8 个字节
日期time表示时间类型
date表示日期类型
datetime同时可以表示日期和时间类型
字符串char(m)固定长度的字符串,无论使用几个字符都占满全部,M 为 0~255 之间的整数
varchar(m)可变长度的字符串,使用几个字符就占用几个,M 为 0~65535 之间的整数
大二进制tinyblobBig Large Object允许长度 0~255 字节
blob允许长度 0~65535 字节
mediumblob允许长度 0~167772150 字节
longblob允许长度 0~4294967295 字节
大文本tinytext允许长度 0~255 字节
text允许长度 0~65535 字节
mediumtext允许长度 0~167772150 字节
longtext允许长度 0~4294967295 字节
创建表

create table employee(

empId int,

empName varchar(10),

deptName varchar(10),

empAge int,

empJoinTime date,

empSalary double(6,2)

) default charset = utf8,engine = innodb;

注意
1.default charset=UTF8,ENGINE=INNODB指定字符集和默认存储引擎

2.我们在数据库中创建了表,现在重启电脑,这个还在不在呢?在

存在位置:C:\ProgramData\MySQL\MySQL Server 5.7\Data\数据库名\表

.frm文件:保存表中的数据,包括表结构的定义等

复制一个表

create table employee2 like employee;

删除表 drop

drop table if exists employee2;

修改表 alter
添加新字段

alter table employee add empBirth date;

修改列类型

alter table employee modify salary int;

修改列名称

alter table employee change salary asalary float;

删除列

alter table employee drop asalary;

修改表名称

rename table employee to emp;

修改表的字符集

alter table emp character set gbk;

查看表结构

desc 表名;

删除外键

alter table employee drop foreign key emp_dept_fk;

DQL

修改数据

updata 表名 set 字段名= 值 where 字段名=条件;

删除数据

delete from 表名 where 条件;

条件查询

select 字段名1,字段名2,…

from 表名

where 分组前条件

group by 分组字段

having 分组后条件

order by 排序字段

limit 分页

select * from employee where id=3;

不等于 != 或<>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bWmXKLF8-1679486971884)(day11.assets/39012dc6b1ba8fcc2c792f93709fa69-16789347172511.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VplbuH2I-1679486971884)(day11.assets/6acdbea81707bee55e170de849075be-16789347244682.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0X5Ua186-1679486971884)(day11.assets/c198cf1f3cb282494b240b83aa5aedd-16789347545973.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r9a5YO1L-1679486971885)(day11.assets/24a57ab6b11da0eceac232f5cb668b8-16789347721794.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bGcWAHuw-1679486971885)(day11.assets/f60db4c227cb3ef9c3b00741923e851-16789347866745.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aK44aPsR-1679486971886)(day11.assets/a64c3050f60403c38faa5e42aba0837.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rfrRRSQq-1679486971886)(day11.assets/887d9a27774bee7e556946ad1e50e3b.png)]

DQL

多表查询

约束和表和表的关系

  1. 约束:约束数据

分类:

  • 主键约束primary key

  • 非空 not null :字段值不能null

  • 唯一unique :值不能重复

  • 外键foreign key :

  • 默认default :

主键约束

一张表中只有一个字段为主键,主键是表中记录的唯一标识,一般选用id作为主键,增删改使用id,主键非空且唯一. auto_increment—主键自增

默认约束

为某一列指定一个默认的规则

外键约束

第一范式:

  • 每一列属性都是不可再分的属性值,确保每一列的原子性
  • 两列的属性相近或相似或一样,尽量合并属性一样的列,确保不产生冗余

第二范式:

  • 每一行的数据只能与其中一列相关,即一行数据只能做一件事

第三范式

  • 数据不能存在传递关系,即每一个属性都跟主键直接关系而不是间接关系

表和表的关系

  • 一对一
  • 一对多:在多的一方建立外键指向另一方的主键.外键和主键类型要一致.多的一方叫做从表,一的一方叫做主表
  • 多对多:创建一个中间表,此表中有两个字段,分别作为两表的外键,这两个字段就是联合主键

constraint emp_dept_fk foreign key(dep_id) references department(id);

级联更新/删除

修改/删除主表时,同时更新从表

alter table employee add constraint emp_depid_fk foreign key(dep_id) references department(id) on update cascade on delete cascade;

联合主键
多表关联查询
连接查询
内连接
  • 隐式内连接

select * from emp,dept where emp.dept_id = dept.id

  • 显示内连接
  • select * from emp inner join dept on emp.dept_id = dept.id;

外连接
  • 左外连接

    select e.,d. from emp e left join dept d on e.dept_id = d.id;(包含左表emp表的所有信息加上关联信息)

  • 右外连接

    select e.name,d.* from dept d right join emp e on e.dept_id = d.id;(包含右表emp的所有信息加上关联信息)

嵌套查询
  • 子查询

    • 子查询分成三种情况

      • 子查询结果是单行单列的,子查询作为where后面条件,使用运算符 > < + <> !=

      • 查询工资小于平均工资的员工

        • select avg(salary) from emp;

        • select * from emp where salary <(select avg(salary) from emp);

      • 子查询结果多行单列的,子查询作为where 后面条件,使用运算符in()

        • select id from dept where name=‘财务部’ or name = ‘市场部’;
        • select * from emp where dept_id in(select id from dept where name=‘财务部’ or name = ‘市场部’);
      • 子查询结果多行多列,子查询结果作为虚拟表参与查询

        • select * from emp where emp.join_date>‘2011-11-11’;
        • select * from dept d,(select * from emp where emp.join_date>‘2011-11-11’) s where d.id = d.dept_id;

select * from emp where salary=(select max(salary) from emp);

事务

insert into account(name,balance) values(‘小王’,1000);

业务:小王给老王转账500

两个步骤:小王账号-500 老王账号+500

开启事务—start transaction;

小王账号-500 ----update account set balance =balance -500 where name = ‘小王’;

老王账号+500----update account set balance = balance + 500 where name = ‘老王’;

回滚—rollback;

提交—commit;

select @@tx_isolation;

事务:如果一个包含很多步骤的业务操作,被事务管理,要么同时成功,要么同时失败

  • 原子性

  • 持久性

  • 隔离性

  • 一致性

事务隔离级别

多个事务之间是隔离的,相互独立的,但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题

  1. 脏读:一个事务,读取到了另一个事务没有提交的数据
  2. 不可重复读(虚读):在同一个事务中,两次读取的数据不一样
  3. 幻读:

隔离级别:

  1. read uncommitted:读未提交
  2. read committed:读已提交
  3. repeatable:可重复读
  4. serializable:串行化

DCL

用户和授权

– 添加自定义用户

create user ‘cat’@‘localhost’ identified by ‘1234’;

create user ‘monkey’@‘%’ identified by ‘1234’;—允许远程连接

–查看用户

select * from user;

–删除用户

drop user ‘monkey’@‘%’;

–修改密码

–使用mysql,针对user表数据操作

–mysql 15.5 mysql 15.7

set password for ‘root’@ ‘localhost’=password(“1234”);

–刷新

flush privileges;

–授权

–查询权限

show grants for ‘cat’@‘localhost’;

–授予权限

grant create,select,update,drop on mydb.account to ‘cat’@‘localhost’;

grant all on mydb.account to ‘cat’@‘localhost’;

– 撤销权限

remove all on mydb.account from ‘cat’@‘localhost’;

数据库备份和还原

备份

msqldump -h localhost -P 3307 -u root -p123456;

JDBC

  1. 导入驱动jar包(mysql-connector-java -5.1.37-bin.java),选中jar包右键选中buid path ->add.
  2. 注册驱动
  3. 获取数据库连接对象Conenction
  4. 定义sql语句
  5. 获取sql的执行对象:Statement PreparedStatement
  6. 执行sql,接收处理返回结果
  7. 释放资源
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接对象Conenction---DriverManager.getConnection(url,user,password);
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3307/mydb1","root","123456");
//jdbc:mysql://localhost:3307/mydb1?useUnicode=true&characterEncoding=UTF-8&useSSL=false;
//定义sql语句
String sql = "select * from department";

//获取sql的执行对象:Statement PreparedStatement
Statement stmt = conn.createStatement();
//执行sql,接收处理返回结果
int count = stmt.executeUpdate(sql);
syso(count);
//释放资源
stmt.close;
conn.close;
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接对象Conenction---DriverManager.getConnection(url,user,password);
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3307/mydb1","root","123456");
//?useUnicode=true&characterEncoding=UTF-8&useSSL=false;
//定义sql语句
String sql="select * from dept";
//获取sql的执行对象:Statement PreparedStatement
Statement stmt = conn.createStatement();
//执行sql,接收处理返回结果
/**--ResultSet结果集:数据封装在结果集中
*next()判断是否有下一行数据
*getXXX(字段名/字段索引)
*/
ResultSet rs= stmt.executeQuery(sql);
while(rs.next()){
   int id = rs.getInt(1);
	String name = rs.getString("name"); 
    System.out.println(id + "--"+name);
}
//释放资源
stmt.close;
conn.close;
package com.gxa.demo02;
/*
 * JDBC工具类:简化JDBC对数据库数据操作的代码书写!!!
 * 配置文件(XXX.properties创建在src)+反射+流
 */

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;



public class JDBCUtils {
	private static String driver;
	private static String url;
	private static String user;
	private static String password;
	//1.注册驱动
	static{
		try {
			//1.1读取配置文件
			Properties pro = new Properties();
			ClassLoader classLoader = JDBCUtils.class.getClassLoader();
			InputStream is = classLoader.getResourceAsStream("jdbc.properties");
			pro.load(is);
			//1.2获取值
			driver = pro.getProperty("driver");
			url = pro.getProperty("url");
			user = pro.getProperty("user");
			password = pro.getProperty("password");
			//1.3注册驱动
			Class.forName(driver);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//2.获取连接
	public static Connection getConnection() throws SQLException{
		return DriverManager.getConnection(url, user, password);
	}
	
	//3.释放资源
	public static void close(ResultSet rs,Statement stmt,Connection conn){
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(stmt!=null){
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

DCL

SQL注入

条件:字符串拼接和单引号

sql = “select * from user where username=? and password=?”;

获取执行对象

PreparedStatement pstmt = conn.prepareStatement(sql);

给?赋值

pstmt.setString (1,username);

pstmt.setString(2,password);

执行sql

rs= pstmt.executeQuery();

return rs.next();

JDBC事务操作

开启事务 start transaction

提交 commit

回滚 rollback

1.注册驱动,获取链接

pro = new Properties();

classLoader = 类名.class.getClassLoader();’

rs =classLoader.getResourceAsStream(“pro.properties”);

pro.load(rs);

driver=properties.getProperty(“driver”);
url=properties.getProperty(“url”);
user=properties.getProperty(“user”);
pwd=properties.getProperty(“pwd”);
Class.forName(driver);

DriverManager.getConnection(url,user,pwd);

2.开启事务

conn.setAutoCommit(false)//false手动提交

3.定义SQL

String sql1 = “update account set balance = balance - 500 where id = 1”;

String sql2 = “update account set balance = balance -+ 500 where id = 2”;

4.获取执行对象

Statement stmt1 = conn.createStatement();

Statement stmt2 = conn.createStatement();

5.执行sql

int count1 = stmt1.executeUpdate(sql1);

int count2 = stmt2.executeUpdate(sql2);

6.提交

conn.conmmit():

7.回滚

catch(){

if(conn!=null){

conn.rollback():

}

}

JDBC:批处理

操作的数据量很大,使用批处理

1.注册驱动,获取连接
2获取Statement对象

statement.addBatch(sql);//将sql语句添加到sql批处理’

3执行批处理

statement.executeBatch();//执行批处理

数据库连接池

当系统初始化好后,容器被创建

c3p0 -三阶段 druid-现在

1.导入druid.jar 包 (add to build path)添加到当前项目中
2.定义配置文件druid.properties

driverName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3307/mydb?useUnicode=true&characterEncoding=UTF-8&useSSL=false;

password=123456

user=root

initialSize=5

maxActive=10

maxWait=3000

3.加载配置文件

pro = new Propertiese():

is = 类名.class.getClassLoader().getResourceAsStream(druid.properties)

pro.load(is);

4.获取数据库连接池对象:通过工厂来获取

ds = DruidDataSourceFactory.createDataSource(pro);

5.获取连接:getConnection

conn = ds.getConnection()

6.插入数据

String sql = “insert into account values(null,?,?)”;

7.获取执行对象

pstmt = conn.prepareStatement(sql);

pstmt.setString(1,“Rosy”);

pstmt.setDouble(2,3000,0);

count = pstmt.executeUpdate();

8.归还连接

conn.close();

pstmt.close():

数据库连接池工具类

static{

pro = new Properties();

id = 类名.class .getClassLoader().getResourceAsStream(“druid.properties”)

pro.load(is);

//获取连接池对象

ds = DruidDataSourceFactory.createDataSource(pro)

}

5.获取连接

return ds.getConnection();

6.释放资源

close(ResultSet ,Connection,Statement)

智慧公交–项目

公交入库:
  • 隔离性

  • 一致性

事务隔离级别

多个事务之间是隔离的,相互独立的,但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题

  1. 脏读:一个事务,读取到了另一个事务没有提交的数据
  2. 不可重复读(虚读):在同一个事务中,两次读取的数据不一样
  3. 幻读:

隔离级别:

  1. read uncommitted:读未提交
  2. read committed:读已提交
  3. repeatable:可重复读
  4. serializable:串行化

DCL

用户和授权

– 添加自定义用户

create user ‘cat’@‘localhost’ identified by ‘1234’;

create user ‘monkey’@‘%’ identified by ‘1234’;—允许远程连接

–查看用户

select * from user;

–删除用户

drop user ‘monkey’@‘%’;

–修改密码

–使用mysql,针对user表数据操作

–mysql 15.5 mysql 15.7

set password for ‘root’@ ‘localhost’=password(“1234”);

–刷新

flush privileges;

–授权

–查询权限

show grants for ‘cat’@‘localhost’;

–授予权限

grant create,select,update,drop on mydb.account to ‘cat’@‘localhost’;

grant all on mydb.account to ‘cat’@‘localhost’;

– 撤销权限

remove all on mydb.account from ‘cat’@‘localhost’;

数据库备份和还原

备份

msqldump -h localhost -P 3307 -u root -p123456;

JDBC

  1. 导入驱动jar包(mysql-connector-java -5.1.37-bin.java),选中jar包右键选中buid path ->add.
  2. 注册驱动
  3. 获取数据库连接对象Conenction
  4. 定义sql语句
  5. 获取sql的执行对象:Statement PreparedStatement
  6. 执行sql,接收处理返回结果
  7. 释放资源
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接对象Conenction---DriverManager.getConnection(url,user,password);
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3307/mydb1","root","123456");
//jdbc:mysql://localhost:3307/mydb1?useUnicode=true&characterEncoding=UTF-8&useSSL=false;
//定义sql语句
String sql = "select * from department";

//获取sql的执行对象:Statement PreparedStatement
Statement stmt = conn.createStatement();
//执行sql,接收处理返回结果
int count = stmt.executeUpdate(sql);
syso(count);
//释放资源
stmt.close;
conn.close;
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接对象Conenction---DriverManager.getConnection(url,user,password);
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3307/mydb1","root","123456");
//?useUnicode=true&characterEncoding=UTF-8&useSSL=false;
//定义sql语句
String sql="select * from dept";
//获取sql的执行对象:Statement PreparedStatement
Statement stmt = conn.createStatement();
//执行sql,接收处理返回结果
/**--ResultSet结果集:数据封装在结果集中
*next()判断是否有下一行数据
*getXXX(字段名/字段索引)
*/
ResultSet rs= stmt.executeQuery(sql);
while(rs.next()){
   int id = rs.getInt(1);
	String name = rs.getString("name"); 
    System.out.println(id + "--"+name);
}
//释放资源
stmt.close;
conn.close;
package com.gxa.demo02;
/*
 * JDBC工具类:简化JDBC对数据库数据操作的代码书写!!!
 * 配置文件(XXX.properties创建在src)+反射+流
 */

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;



public class JDBCUtils {
	private static String driver;
	private static String url;
	private static String user;
	private static String password;
	//1.注册驱动
	static{
		try {
			//1.1读取配置文件
			Properties pro = new Properties();
			ClassLoader classLoader = JDBCUtils.class.getClassLoader();
			InputStream is = classLoader.getResourceAsStream("jdbc.properties");
			pro.load(is);
			//1.2获取值
			driver = pro.getProperty("driver");
			url = pro.getProperty("url");
			user = pro.getProperty("user");
			password = pro.getProperty("password");
			//1.3注册驱动
			Class.forName(driver);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//2.获取连接
	public static Connection getConnection() throws SQLException{
		return DriverManager.getConnection(url, user, password);
	}
	
	//3.释放资源
	public static void close(ResultSet rs,Statement stmt,Connection conn){
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(stmt!=null){
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

DCL

SQL注入

条件:字符串拼接和单引号

sql = “select * from user where username=? and password=?”;

获取执行对象

PreparedStatement pstmt = conn.prepareStatement(sql);

给?赋值

pstmt.setString (1,username);

pstmt.setString(2,password);

执行sql

rs= pstmt.executeQuery();

return rs.next();

JDBC事务操作

开启事务 start transaction

提交 commit

回滚 rollback

1.注册驱动,获取链接

pro = new Properties();

classLoader = 类名.class.getClassLoader();’

rs =classLoader.getResourceAsStream(“pro.properties”);

pro.load(rs);

driver=properties.getProperty(“driver”);
url=properties.getProperty(“url”);
user=properties.getProperty(“user”);
pwd=properties.getProperty(“pwd”);
Class.forName(driver);

DriverManager.getConnection(url,user,pwd);

2.开启事务

conn.setAutoCommit(false)//false手动提交

3.定义SQL

String sql1 = “update account set balance = balance - 500 where id = 1”;

String sql2 = “update account set balance = balance -+ 500 where id = 2”;

4.获取执行对象

Statement stmt1 = conn.createStatement();

Statement stmt2 = conn.createStatement();

5.执行sql

int count1 = stmt1.executeUpdate(sql1);

int count2 = stmt2.executeUpdate(sql2);

6.提交

conn.conmmit():

7.回滚

catch(){

if(conn!=null){

conn.rollback():

}

}

JDBC:批处理

操作的数据量很大,使用批处理

1.注册驱动,获取连接
2获取Statement对象

statement.addBatch(sql);//将sql语句添加到sql批处理’

3执行批处理

statement.executeBatch();//执行批处理

数据库连接池

当系统初始化好后,容器被创建

c3p0 -三阶段 druid-现在

1.导入druid.jar 包 (add to build path)添加到当前项目中
2.定义配置文件druid.properties

driverName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3307/mydb?useUnicode=true&characterEncoding=UTF-8&useSSL=false;

password=123456

user=root

initialSize=5

maxActive=10

maxWait=3000

3.加载配置文件

pro = new Propertiese():

is = 类名.class.getClassLoader().getResourceAsStream(druid.properties)

pro.load(is);

4.获取数据库连接池对象:通过工厂来获取

ds = DruidDataSourceFactory.createDataSource(pro);

5.获取连接:getConnection

conn = ds.getConnection()

6.插入数据

String sql = “insert into account values(null,?,?)”;

7.获取执行对象

pstmt = conn.prepareStatement(sql);

pstmt.setString(1,“Rosy”);

pstmt.setDouble(2,3000,0);

count = pstmt.executeUpdate();

8.归还连接

conn.close();

pstmt.close():

数据库连接池工具类

static{

pro = new Properties();

id = 类名.class .getClassLoader().getResourceAsStream(“druid.properties”)

pro.load(is);

//获取连接池对象

ds = DruidDataSourceFactory.createDataSource(pro)

}

5.获取连接

return ds.getConnection();

6.释放资源

close(ResultSet ,Connection,Statement)

智慧公交–项目

公交入库:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值