java笔记03-常用工具

文章目录

一. java异常

1. 介绍

  1. 如何应用异常处理程序中的问题
  2. 如果通过包装器类实现基本数据类型的对象化处理
  3. 字符串处理类,String, StringBuilder 是如何进行字符串信息操作的.
  4. 常用集合框架及实现类的使用
  5. 如何使用Java输入输出流进行文件的读写
  6. 如何使用多线程实现数据之间的并发通信

如何处理异常

  • try-catch-finally
  • throw
  • throws
  • 自定义异常

2. 什么是异常

  • 异常本质上是程序上的错误.
  • 错误在我们编写程序的过程中会经常发生, 包括编译期间和运行期间的错误.
  • 在程序运行过程中, 意外发生的情况,背离我们程序本身的意图的表现,都可以理解为异常.

3. 异常分类

在这里插入图片描述

4. 异常处理分类

  • 在java应用程序中, 异常处理机制为:
  1. 抛出异常
  2. 捕捉异常

对于运行时异常, 错误或可查异常, java技术所要求的异常处理方式有所不同

  1. 对于可查异常必须捕捉, 或者声明抛出
  2. 允许忽略不可查的 RuntimeException(含子类)和Error(含子类).

通过5个关键字来实现

  1. try
  2. catch
  3. finally
  4. throw
  5. throws

在这里插入图片描述

5. try-catch-finally

实际应用中的经验与总结

  1. 处理运行时异常时, 采用逻辑去合理规避同时辅助 try-catch 处理
  2. 在多重catch 块后面, 可以加一个 catch (Exception) 来处理可能会被遗漏的异常
  3. 对于不确定的代码, 也可以加上 try-catch, 处理潜在的异常
  4. 尽量去处理异常, 切忌只是简单的调用 printStackTrace() 去打印输出
  5. 具体如何处理异常, 要根据不同的业务需求和异常类型去决定
  6. 尽量添加 finally 语句块去释放占用的资源

语法

public void method(){
	try{
		//代码块1
		//产生异常的代码块2
	}catch(异常类型 ex){
		//以异常进行处理的代码段3
	}finally{
		//代码段4
	}
}
  • try 块后可以接零个或多个catch块, 如果没有catch块,则必须跟一个 finally 块.

6. 使用try-catch结构处理异常

package com.imooc.test;

import java.util.InputMismatchException;
import java.util.Scanner;

public class TryDemoOne {

	public static void main(String[] args) {
		// 要求: 定义2个整数,接受用户的键盘输入,输出2数之商
		Scanner input = new Scanner(System.in);

		try {
			System.out.println("=====运算开始=====");
			System.out.print("请输入第一个整数:");
			int one = input.nextInt();
			System.out.print("请输入第二个整数:");
			int two = input.nextInt();
			System.out.println("one和two的商为" + (one / two));
		} catch (ArithmeticException e) {
			System.out.println("除数不允许为0");
			e.printStackTrace();
		}catch (InputMismatchException e) {
			System.exit(1);  //强行终止程序的运行
			System.out.println("请输入整数");
			e.printStackTrace();
		} catch (Exception e) {
			System.out.println("出错了~~~");
			e.printStackTrace();
		} finally {
			System.out.println("=====运算结束=====");
		}

	}

}

7. 使用多重catch结构处理异常

  • 如上示例

8. 终止finally执行的方法

  • System.exit(1); 强制中止程序运行! 参数是一个非0的参数.

9. return关键字的异常处理中的作用

  • 当 try, catch, finally 中都有return的时候,最终都会返回 finally中的return数据.
  • 建议 finally 里面不要写return. 因为 finally里面的代码块是强制执行的,所以 其他try, catch中return就被屏蔽了.
package com.imooc.test;

import java.util.Scanner;

public class TryDemoTwo {
	public static void main(String[] args) {
		int result = test();
		System.out.println("one和two的商为" + result);
	}

	public static int test() {
		Scanner input = new Scanner(System.in);
		System.out.println("=====运算开始=====");

		try {
			System.out.print("请输入第一个整数:");
			int one = input.nextInt();
			System.out.print("请输入第二个整数:");
			int two = input.nextInt();
			return one / two;
		} catch (ArithmeticException e) {
			System.out.println("除数不允许为0");
			return 0;
		} finally {
			System.out.println("=====运算结束=====");
//			return -100000;
		}
	}

}

10. 使用throws声明异常类型

  • 可以通过 throws 声明将要抛出何种类型的异常, 通过 throw 将产生的异常抛出.
  • 如果一个方法可能会出现异常, 但没有能力处理这种异常, 可以在方法声明处用 throws 子句来声明抛出异常.
  • throws 语句用在方法定义时声明该方法要抛出的异常类型
public void method() throws Exception1, Exception2, ..., ExceptionN{
	// 可能产生异常的代码
}
  • 当方法抛出异常列表中的异常时, 方法将不对这些类型及其子类类型的异常作处理, 而抛向调用该方法的方法, 由他去处理.

示例

package com.imooc.test;

import java.util.InputMismatchException;
import java.util.Scanner;

public class TryDemoThree {
	public static void main(String[] args) {
		try {
			int result = test();
			System.out.println("one和two的商为" + result);
		} catch (InputMismatchException e) {
			System.out.println("必须是数字");
//			e.printStackTrace();
		} catch (ArithmeticException e) {
			System.out.println("除数不允许为0");
//			e.printStackTrace();
		}
	}

	public static int test() throws ArithmeticException, InputMismatchException {
		Scanner input = new Scanner(System.in);
		System.out.println("=====运算开始=====");

		System.out.print("请输入第一个整数:");
		int one = input.nextInt();
		System.out.print("请输入第二个整数:");
		int two = input.nextInt();

		System.out.println("=====运算结束=====");
		return one / two;

	}
}

通过throws抛出异常时, 针对可能出现的多中异常情况,解决方案:

  1. throws 后面接多个异常类型, 中间用逗号分隔, 示例如上.
  2. throws 直接抛出父类 Exception.
package com.imooc.test;

import java.util.InputMismatchException;
import java.util.Scanner;

public class TryDemoThree {
	public static void main(String[] args) {
		try {
			int result = test();
			System.out.println("one和two的商为" + result);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static int test() throws Exception {
		Scanner input = new Scanner(System.in);
		System.out.println("=====运算开始=====");

		System.out.print("请输入第一个整数:");
		int one = input.nextInt();
		System.out.print("请输入第二个整数:");
		int two = input.nextInt();

		System.out.println("=====运算结束=====");
		return one / two;

	}
}

11. 使用throw抛出异常对象

  • throw 用来抛出一个异常.

例如: throw new IOException();

  • throw 抛出的只能够是可抛出类 Throwable 或者其子类的实例对象.

例如: throw new String(“出错啦”); 这个是 String类型的, 所以这样写是错误的.

throw的2种写法

  1. 方案一, 如下格式
public void method(){
	try{
		//代码段1
		throw new 异常类型();
	}catch(异常类型 ex){
		// 对异常进行处理的代码段2
	}
}
  1. 方案二, 如下格式
public void method() throws 异常类型{
	//代码段1
	throw new 异常类型();
}

throw抛出异常对象的处理方案

  1. 通过 try…catch包含throw语句-- 自己抛出异常,自己处理
  2. 通过 throws 在方法声明处抛出异常类型 – 谁调动谁处理 – 调用者可以自己处理, 也可以继续上抛.

示例

package com.imooc.test;

import java.util.Scanner;

public class TryDemoFour {
	public static void main(String[] args) {
		try {
			testAge();
		} catch (Exception e) {
			System.out.println(e.getMessage());
			System.out.println("酒店前台工作人员不允许办理入住登记");
		}
	}

	// 描述酒店的入住规则: 限定年龄,18岁以下,80岁以上的住客需要由亲友陪同
	public static void testAge() throws Exception {
		System.out.print("请输入年龄:");
		Scanner input = new Scanner(System.in);
		int age = input.nextInt();
		if (age < 18 || age > 80) {
			throw new Exception();
		} else {
			System.out.println("欢迎入住");
		}

	}
}

12. 自定义异常类

  • 使用java内置的异常类可以描述在编程时出现的大部门异常情况.
  • 也可以通过自定义异常描述特定业务产生的异常类型.
  • 所谓自定义异常, 就是定义一个类, 去继承 Throwable 类或者它的子类.

示例

package com.imooc.test;

public class HotelAgeException extends Exception {
	public HotelAgeException() {
		super("18岁以下,80岁以上的住客需要由亲友陪同");
	}
}

调用

throw new HotelAgeException();

完整调用例子

package com.imooc.test;

import java.util.Scanner;

public class TryDemoFour {
	public static void main(String[] args) {
		try {
			testAge();
		} catch (HotelAgeException e) {
			System.out.println(e.getMessage());
			System.out.println("酒店前台工作人员不允许办理入住登记");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 描述酒店的入住规则: 限定年龄,18岁以下,80岁以上的住客需要由亲友陪同
	public static void testAge() throws HotelAgeException {
		System.out.print("请输入年龄:");
		Scanner input = new Scanner(System.in);
		int age = input.nextInt();
		if (age < 18 || age > 80) {
			throw new HotelAgeException();
		} else {
			System.out.println("欢迎入住");
		}

	}
}

13. 异常链简介

  • 有时候我们会捕获一个异常后在抛出另一个异常.
  • 顾名思义就是: 将异常发生的原因一个传一个串起来, 即把底层的异常信息传给上层, 这样逐层抛出.

示例如下

package com.imooc.test;

public class TryDemoFive {
	public static void main(String[] args) {
		try {
			testThree();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void testOne() throws HotelAgeException {
		throw new HotelAgeException();
	}

	public static void testTwo() throws Exception {
		try {
			testOne();
		} catch (HotelAgeException e) {
			throw new Exception("我是新产生的异常1", e);
		}
	}

	public static void testThree() throws Exception {
		try {
			testTwo();
		} catch (Exception e) {
			Exception e1 = new Exception("我是新产生的异常2");
			e1.initCause(e);
			throw e1;
//			throw new Exception("我是新产生的异常2", e);
		}
	}

}

14. 关于方法重写时throws的注意事项

throw & throws

  • 可以通过 throws 声明将要抛出何种类型的异常, 通过 throw将产生的异常抛出.
  • 如果一个方法可能会出现异常, 但没有能力处理这种异常, 可以在方法声明处用 throws 字句来声明抛出异常.

throw

  • 当子类重写父类抛出异常的方法时, 声明的异常必须是父类方法所声明异常的同类或子类.

二. java包装类

1. 包装类与基本数据类型

在这里插入图片描述

  • 包装类就是为了解决 基本数据类型 没有属性,方法,无法对象化交互的问题.
  • 包装类可以让 基本数据类型 拥有属性,方法, 可以对象化交互.

基本数据类型和对应的包装类

基本类型对应的包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

2. 包装类常用方法

  • https://docs.oracle.com/javase/8/docs/api/ 文档

3. 基本数据和包装类之间的转换

  • 装箱: 把基本数据类型的值 转为 包装类的对象
  • 拆箱: 把包装类的对象 转为 基本数据类型的值

包装类的获取值方法

数据类型包装类方法
bytebyteValue()
intintValue()
doubledoubleValue()
floatfloatValue()
longlongValue()
shortshortValue()

示例

package wrap;

public class WrapTestDemo {
	public static void main(String[] args) {
		// 装箱: 把基本数据类型转换为包装类
		// 1. 自动装箱
		int t1 = 2;
		Integer t2 = t1;

		// 2. 手动装箱
		Integer t3 = new Integer(t1);

		// 测试
		System.out.println("int类型变量t1=" + t1);
		System.out.println("Integer类型对象t2=" + t2);
		System.out.println("Integer类型对象t3=" + t3);

		System.out.println("******************************");

		// 拆箱: 把包装类转换为基本数据类型
		// 1.自动拆箱
		int t4 = t2;

		// 2.手动拆箱
		int t5 = t2.intValue();

		// 测试
		System.out.println("Integer类型对象t2=" + t2);
		System.out.println("自动拆箱后,int类型变量t4=" + t4);
		System.out.println("自动拆箱后,int类型变量t5=" + t5);

		double t6 = t2.doubleValue();
		System.out.println("自动拆箱后,double类型变量t6=" + t6);

	}
}

4. 基本数据类型和字符串之间的转换

基本数据类型 转为 字符串

String t2 = Integer.toString(t1);

字符串 转为 基本数据类型

  1. 包装类的 parse 方法

int t3 = Integer.praseInt(t2);

  1. 包装类的 valueOf 方法,先将字符串转换为包装类, 再通过自动拆箱完成基本数据转换

int t4 = Integer.valueOf(t2);

完整示例

package wrap;

public class WrapTestTwo2 {

	public static void main(String[] args) {
		// 基本数据类型转换为字符串
		int t1 = 2;
		String t2 = Integer.toString(t1);
		// 测试
		System.out.println("int类型转换为String类型对象t2=" + t2);

		System.out.println("***************");
		// 字符串转换为基本数据类型
		// 1. 包装类的 parse方法
		int t3 = Integer.parseInt(t2);
		// 2. 包装类的 valueOf 方法,先将字符串转换为包装类, 再通过自动拆箱完成基本数据转换
		int t4 = Integer.valueOf(t2);
		System.out.println("String类型转换为int类型变量t3=" + t3);
		System.out.println("String类型转换为int类型变量t4=" + t4);
	}

}

5. 需要知道的几点知识

  • 包装类对象的初始值
  • 包装类对象间的比较
package wrap;

public class Cat1Test {

	public static void main(String[] args) {
		// 实例化对象
		Cat1 one1 = new Cat1();

		// 测试输出
		System.out.println("小猫的昵称:" + one1.name);
		System.out.println("小猫的年龄:" + one1.month);
		System.out.println("小猫的体重:" + one1.weight);

		Integer one = new Integer(100);
		Integer two = new Integer(100);

		System.out.println("one==tow的结果" + (one == two)); //false

		Integer three = 100;
		// 自动拆箱
		System.out.println("three=100的结果:" + (three == 100)); //true

		Integer four = 100;
		System.out.println("three==four的结果:" + (three == four)); //true

		Integer five = 200;
		System.out.println("five == 200的结果: " + (five == 200)); //true

		Integer six = 200;
		System.out.println("five==xie的结果:" + (five == six)); //false

	}

}



三. java字符串

1. String 常用方法

创建String对象的常见3种方式

  1. String s1 = “imooc”; 创建一个字符串对象 imooc, 名为 s1
  2. String s2 = new String(); 创建一个空字符串对象, 名为 s2
  3. String s3 = new String(“imooc”); 创建一个字符串对象 s3, 并赋值 imooc

String 常用方法

方法说明
int length()返回当前字符串的长度
int indexOf(int ch)查找ch字符在该字符串中第一次出现的位置
int indexOf(String str)查找str子字符串在该字符串中第一次出现的位置
int lastIndexOf(int ch)查找ch字符在该字符串中最后一次出现的位置
int lastIndexOf(String str)查找str子字符串在该字符串中最后一次出现的位置
String substring(int beginIndex)获取从beginIndex位置开始到结束的子字符串
String substring(int beginIndex, int endIndex)获取从beginIndex位置开始到endIndex位置的子字符串
String trim()返回去除了前后空格的字符串
boolean equals(Object obj)将该字符串与指定对象比较, 返回true或false
String toLowerCase()将字符串转换为小写
String toUpperCase()将字符串转换为大写
char charAt(int index)获取字符串中指定位置的字符
String[] split(String regex, int limit)将字符串分割为子字符串,返回字符串数组
byte[] getBytes()将该字符串转换为 byte 数组

举例

  • length(), charAt(), substring() 方法
package com.imooc.string1;

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

		// 定义一个字符串 "JAVA 编程基础"
		String str = "JAVA 编程 基础";

		// 打印输出字符串的长度
		System.out.println("字符串的长度是" + str.length());  //10
		
		// 打印 '程' 字, charAt(int index)
		System.out.println(str.charAt(6));  //程
		
		// 取出字串 "编程 基础"并输出
		System.out.println(str.substring(5)); //编程 基础

		// 取出字串 "编程" 并输出
		System.out.println(str.substring(5, 7)); //编程
		
	}
}
  • indexOf(), lastIndexOf()
package com.imooc.string1;

public class StringDemo2 {

	public static void main(String[] args) {
		// 定义一个字符串 "JAVA编程基础,我喜欢java编程"
		String str = new String("JAVA编程基础,我喜欢java编程");

		// 1.查找字符 'A'在字符串中第一次出现的位置
		System.out.println("字符'A'在字符串中第一次出现的位置: " + str.indexOf('A')); // 1

		// 2.查找字串"编程"在字符串中第一次出现的位置
		System.out.println("字串\"编程\"在字符串中第一次出现的位置: " + str.indexOf("编程")); // 4

		// 3.查找字符 'A'在字符串中第后一次出现的位置
		System.out.println("字符'A'在字符串中第后一次出现的位置: " + str.lastIndexOf('A')); // 3

		// 4.查找字串"编程"在字符串中第后一次出现的位置
		System.out.println("字符\"编程\"在字符串中第后一次出现的位置: " + str.lastIndexOf("编程")); // 16

		// 5. 在字符串index的值为8的位置开始, 查找字串 "编程" 第一次出现的位置
		System.out.println("在字符串index的值为8的位置开始, 查找字串 \"编程\" 第一次出现的位置是: " + str.indexOf("编程", 8)); //16
	}

}
  • getBytes() 方法 将该字符串转换为 byte 数组
  • String(byte[] bytes) 构造方法,可以将 byte数组转为字符串
package com.imooc.string1;

public class StringDemo3 {

	public static void main(String[] args) {
		// 字符串和 byte数组之间的相互转换
		// 定义一个字符串
		String str = new String("JAVA 编程 基础");
		// 将字符串转换为 byte 数组,并打印输出
		byte[] arrs = str.getBytes();
		for (int i = 0; i < arrs.length; i++) {
			//74 65 86 65 32 -25 -68 -106 -25 -88 -117 32 -27 -97 -70 -25 -95 -128 
			System.out.print(arrs[i] + " ");
		}

		System.out.println();
		// 将byte数组转换为字符串
		String str1 = new String(arrs);
		System.out.println(str1);  //JAVA 编程 基础

	}

}

2. 等于运算符与equals方法的区别

  • “==” 指的是 2个对象的引用是否相同
  • equals() 方法指的是 2个对象的值 是否相同

在这里插入图片描述
例子如下

package com.imooc.string1;

public class StringDemo5 {

	public static void main(String[] args) {
		// == 和 equals 方法之间的区别
		// 定义三个字符串,内容都是 imooc
		String str1 = "imooc";
		String str2 = "imooc";
		String str3 = new String("imooc");

		System.out.println("str1和str2的内容相同?" + str1.equals(str2));  //true
		System.out.println("str1和str3的内容相同?" + str1.equals(str3));  //true

		System.out.println("str1和str2的地址相同?" + (str1 == str2)); //true
		System.out.println("str1和str3的地址相同?" + (str1 == str3)); //false

	}

}

3. 字符串的不可变性

  • String 对象一旦被创建,则不能修改,是不可变的
  • 所谓的修改其实是创建了新的对象, 所指向的内容空间不变

例子

package com.imooc.string1;

public class StringDemo6 {

	public static void main(String[] args) {

		// String的不可变性
		// String 对象一旦被创建,则不能修改,是不可变的
		// 所谓的修改其实是创建了新的对象, 所指向的内容空间不变
		String s1 = "imooc";
		String s2 = "hello, " + s1;
		// s1不再指向imooc所在的内存空间,而是指向了 "hello,imooc"
		System.out.println("s1=" + s1); // imooc
		System.out.println("s2=" + s2); // hello, imooc

		String s3 = new String("hello,imooc!");
		System.out.println("字串:" + s3.substring(0, 5));
		System.out.println("s3=" + s3);
	}
}

4. StringBuilder 概述

String和StringBuilder的区别

  • String 具有不可变性, 而 StringBuilder不具备

建议

  • 当频繁操作字符串时,使用 StringBuilder.

StringBuilder和StringBuffer

  1. 二者基本相似
  2. StringBuffer 是线程安全的, StringBuilder则没用, 所以性能略高.

5. StringBuilder常用方法

  • StringBuilder append(String str) 添加方法
  • StringBuilder delete(int start, int end) 删除方法
  • StringBuilder insert(int offset, String str) 插入方法
  • StringBuilder replace(int start, int end, String str) 替换方法
package com.imooc.string1;

public class StringBuilderDemo1 {

	public static void main(String[] args) {
		// 定义一个字符串 "你好"
		StringBuilder str = new StringBuilder("你好");
		// 在"你好"后面添加内容,将字符串变成 "你好,imooc"

		/*
		 * 写法一
		 * 
		 * str.append(','); str.append("imooc"); System.out.println("str=" + str);
		 */

		/*
		 * 写法二
		 */
		System.out.println("str=" + str.append(',').append("imooc")); // str=你好,imooc

		// 将字符串变成 "你好,IMOOC"
		// 两种方式
		/*
		 * 1. 使用delete方法删除imooc, 然后再插入 IMOOC
		 * 
		 * System.out.println("替换后: " + str.delete(3, 8).insert(3, "IMOOC"));
		 */

		// 2. 使用 replace 方法直接替换
		System.out.println("替换后: " + str.replace(3, 8, "IMOOC")); // 替换后: 你好,IMOOC

		// 3. 在字符串 "你好,IMOOC" 中取出 "你好" 并输出
		System.out.println(str.substring(0, 2)); // 你好
	}

}


四. java集合

1. 集合概述

  • 概念

  • 体系结构

  • 实际应用

  • java 中的集合是工具类,可以存储任意数量的具有共同属性的对象.

应用场景

  • 无法预测存储数据的数量
  • 同时存储具有一对一关系的数据
  • 需要进行数据的增删
  • 数据重复问题

2. 集合框架的体系结构

  • Collection 存放对象
  • Map 存放键值对
    在这里插入图片描述

3. list(列表)概述

  • List是元素有序并且可以重复的集合, 称为序列.
  • List 可以精确的控制每个元素的插入位置, 或删除某个位置的元素
  • List 的两个主要实现类是 ArrayList 和 LinkedList

ArrayList

  • ArrayList 底层是由数组实现的
  • 动态增长, 以满足应用程序的需要
  • 在列表尾部插入或删除数据非常有效
  • 更适合查找和更新元素
  • ArrayList 中的元素可以为 null

4. 案例:在list中存储并操作字符串信息

ArrayList() 的常见方法

  • add() 添加元素
  • size() 查看 ArrayList() 中元素的个数
  • get(Int index) 根据下标查看元素
  • remove(Int index) / remove(Object o) 移出元素,可以接下标或者字符串的值.

例子

package com.imooc.set1;

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

public class ListDemo1 {

	public static void main(String[] args) {
		// 用ArrayList存储编程语言的名称, 并输出
		List list = new ArrayList();
		// 添加内容
		list.add("JAVA");
		list.add("C");
		list.add("C++");
		list.add("Go");
		list.add("swift");

		// 输出列表中元素的个数
		System.out.println("列表中元素的个数为: " + list.size()); // 列表中元素的个数为: 5

		System.out.println("**********************");
		// 遍历输出所有的编程语言
		for (int i = 0; i < list.size(); i++) {
			System.out.print(list.get(i) + " "); // JAVA C C++ Go swift
		}

		System.out.println("");
		/**
		 * 移出列表中的 C++ 方法一
		 * 
		 * list.remove(2); // 遍历输出所有的编程语言 
		 * for (int i = 0; i < list.size(); i++) {
		 * 		System.out.print(list.get(i) + " "); //JAVA C Go swift 
		 * }
		 */

		System.out.println("");

		/**
		 * 移出列表中的 C++ 方法二
		 */
		list.remove("C++");
		for (int i = 0; i < list.size(); i++) {
			System.out.print(list.get(i) + " "); // JAVA C Go swift
		}

	}

}

5. 公告需求管理

  • 在 ArrayList() 中添加 自定义类 的对象.

公告需求管理 需求

  • 公告的添加和显示
  • 在指定位置处插入广告
  • 删除公告
  • 修改公告

公告类属性

  • 编号 id
  • 标题 title
  • 创建人 creator
  • 创建时间 createTime

公告类方法

  • 构造方法
  • 获取和设置属性值的方法

6. 案例:公告类添加和实现

需求

  • 公告的添加和显示
  • 在指定位置处出入广告
  • 删除公告

公告类

package com.imooc.set1;

import java.util.Date;

public class Notice {
	private int id; // ID
	private String title; // 标题
	private String creator; // 创建人
	private Date createTime; // 创建时间

	public Notice() {
	}

	public Notice(int id, String title, String creator, Date createTime) {
		this.setId(id);
		this.setTitle(title);
		this.setCreator(creator);
		this.setCreateTime(createTime);
	}

	public int getId() {
		return id;
	}

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

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getCreator() {
		return creator;
	}

	public void setCreator(String creator) {
		this.creator = creator;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

}

公告测试类

package com.imooc.set1;

import java.util.ArrayList;
import java.util.Date;

public class NoticeTest {

	public static void main(String[] args) {
		// 创建Notice类的对象, 生成三条公告
		Notice notice1 = new Notice(1, "欢迎来到mooc", "管理员", (new Date()));
		Notice notice2 = new Notice(2, "请同学们按时提交作业", "老师", (new Date()));
		Notice notice3 = new Notice(3, "考勤通知", "老师", (new Date()));

		// 添加公告
		ArrayList noticeList = new ArrayList();
		noticeList.add(notice1);
		noticeList.add(notice2);
		noticeList.add(notice3);

		// 显示公告
		for (int i = 0; i < noticeList.size(); i++) {
			System.out.println(i + 1 + ": " + ((Notice) (noticeList.get(i))).getTitle() + " ");
		}
		/**
		 * 输出 
		 * 1: 欢迎来到mooc 
		 * 2: 请同学们按时提交作业 
		 * 3: 考勤通知
		 * 
		 */
		
		
	}
}

PS: ((Notice) (noticeList.get(i))).getTitle() 这里的解释:

  1. noticeList.get(i) 获取到的是 Object 对象.
  2. (Notice) (noticeList.get(i))) 将 Object对象转为 Notice 对象.
  3. ((Notice) (noticeList.get(i))).getTitle() 调用 Notice 对象的getTitle() 来获取标题. 注意括号.

7. 案例:公告的删除和修改

在指定位置添加公告 - add() 方法

// 在第一条公告后面添加一条新的公告 add() 方法
Notice notice4 = new Notice(4, "在线编辑器可以使用了!", "管理员", (new Date()));

noticeList.add(1, notice4);

删除公告 - remove() 方法

noticeList.remove(2);

修改公告 - set() 方法

Notice notice4 = new Notice(4, "在线编辑器可以使用了!", "管理员", (new Date()));
...
notice4.setTitle("Java在线编辑器可以使用啦!");
noticeList.set(1, notice4);

完整代码

package com.imooc.set1;

import java.util.ArrayList;
import java.util.Date;

public class NoticeTest {

	public static void main(String[] args) {
		// 创建Notice类的对象, 生成三条公告
		Notice notice1 = new Notice(1, "欢迎来到mooc", "管理员", (new Date()));
		Notice notice2 = new Notice(2, "请同学们按时提交作业", "老师", (new Date()));
		Notice notice3 = new Notice(3, "考勤通知", "老师", (new Date()));

		// 添加公告
		ArrayList noticeList = new ArrayList();
		noticeList.add(notice1);
		noticeList.add(notice2);
		noticeList.add(notice3);

		// 在第一条公告后面添加一条新的公告
		Notice notice4 = new Notice(4, "在线编辑器可以使用了!", "管理员", (new Date()));

		noticeList.add(1, notice4);
		// 显示公告
		for (int i = 0; i < noticeList.size(); i++) {
			System.out.print(i + 1 + ": " + ((Notice) (noticeList.get(i))).getTitle() + " ");
		}
		// 输出: 1: 欢迎来到mooc 2: 在线编辑器可以使用了! 3: 请同学们按时提交作业 4: 考勤通知

		System.out.println("**************");

		// 删除按时完成作业的公告
		noticeList.remove(2);
		// 显示公告
		for (int i = 0; i < noticeList.size(); i++) {
			System.out.print(i + 1 + ": " + ((Notice) (noticeList.get(i))).getTitle() + " ");
		}
		// 输出: 1: 欢迎来到mooc 2: 在线编辑器可以使用了! 3: 考勤通知

		// 修改公告, 将第二条公告改为: Java在线编辑器可以使用啦!
		System.out.println("**************");
		// 先修改第二条公告中 title 的值

		notice4.setTitle("Java在线编辑器可以使用啦!");
		noticeList.set(1, notice4);
		// 显示公告
		for (int i = 0; i < noticeList.size(); i++) {
			System.out.print(i + 1 + ": " + ((Notice) (noticeList.get(i))).getTitle() + " ");
		}
		//输出: 欢迎来到mooc 2: Java在线编辑器可以使用啦! 3: 考勤通知 

	}
}

8. set概述

  • Set是元素无序并且不可以重复的集合, 被称为 .
  • HashSet 是 Set 的一个重要实现类, 称为 哈希集.
  • HashSet 中的元素无序并且不可以重复.
  • HashSet 中只允许一个 null 元素.
  • 具有良好的存取和查找性能.

9. Iterator(迭代器)

Iterator接口以统一的方式对各种集合元素进行遍历

Iterator<String> it = set.iterator();
while(it.hasNext()){
	System.out.println(it.next() + " ");
}
  • Iterator 接口 可以以统一的方式对各种集合元素进行遍历
  • hasNext() 方法检测集合中是否还有下一个元素
  • next() 方法返回集合中的下一个元素

迭代器的使用示例

package com.imooc.set1;

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

public class WordDemo {

	public static void main(String[] args) {
		// 将英文单词添加到 HashSet 中
		Set set = new HashSet();
		// 向集合中添加元素
		set.add("blue");
		set.add("red");
		set.add("black");
		set.add("yellow");
		set.add("white");

		// 显示集合的内容
		System.out.println("集合中的元素为:");

		// 使用迭代器, 把数据放到 迭代器中
		Iterator it = set.iterator();
		// 遍历迭代器并输出元素
		while (it.hasNext()) {
			System.out.print(it.next() + " "); // 输出: red blue white black yellow
		}

	}

}

  • Set 中是不允许有重复数据的,如果插入相同数据了, eclipse中不会提示错误,但是会插入失败.
  • Set 中的数据是无序不允许重复的,所以和列表不同,不存在在一个位置插入数据.

10. HashSet中添加自定义类的对象

案例: 宠物猫信息管理

需求

  • 添加和显示宠物猫信息
  • 查找某只宠物猫的信息并输出
  • 修改宠物猫的信息
  • 删除宠物猫的信息

属性

  • 名字 name
  • 年龄 month
  • 品种 species

方法

  • 构造方法
  • 获取和设置属性值的方法
  • 其他方法

11. 添加和显示信息

  • HashSet 添加信息 add()
  • HashSet 显示信息,用 迭代器实现.

具体实现

  1. Cat 类
package com.imooc.set1;

public class Cat {

	private String name; // 名字
	private int month; // 年龄
	private String species; // 品种

	// 构造方法
	public Cat() {
	}

	public Cat(String name, int month, String species) {
		this.setName(name);
		this.setMonth(month);
		this.setSpecies(species);
	}

	// getter和setter
	public String getName() {
		return name;
	}

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

	public int getMonth() {
		return month;
	}

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

	public String getSpecies() {
		return species;
	}

	public void setSpecies(String species) {
		this.species = species;
	}

	@Override
	public String toString() {
		return " [姓名: " + name + ", 年龄: " + month + ", 品种: " + species + "]";
	}
	
	

}

  1. 测试类
package com.imooc.set1;

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

public class CatTest {

	public static void main(String[] args) {
		// 定义宠物猫类
		Cat huahua = new Cat("花花", 12, "英国短毛猫");
		Cat fanfan = new Cat("凡凡", 3, "中华田园猫");

		// 将宠物猫对象放入HashSet中
		Set set = new HashSet();
		set.add(huahua);
		set.add(fanfan);

		// 显示宠物猫信息
		Iterator it = set.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}

	}

}

插入重复数据

  • 注意: 这里插入重复的自定义类对象的时候, 需要重写 hashCode() 和 equals() 方法. 代码如下
package com.imooc.set1;

public class Cat {

	private String name; // 名字
	private int month; // 年龄
	private String species; // 品种

	// 构造方法
	public Cat() {
	}

	public Cat(String name, int month, String species) {
		this.setName(name);
		this.setMonth(month);
		this.setSpecies(species);
	}

	// getter和setter
	public String getName() {
		return name;
	}

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

	public int getMonth() {
		return month;
	}

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

	public String getSpecies() {
		return species;
	}

	public void setSpecies(String species) {
		this.species = species;
	}

	@Override
	public String toString() {
		return " [姓名: " + name + ", 年龄: " + month + ", 品种: " + species + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + month;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((species == null) ? 0 : species.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		// 判断对象 是否相等, 相等则返回true, 不用继续比较属性了
		if (this == obj) {
			return true;
		}
		// 判断obj是否是Cat类的对象
		if (obj.getClass() == Cat.class) {
			Cat cat = (Cat) obj;
			return (cat.getName().equals(name)) && (cat.getMonth() == month) && (cat.getSpecies().equals(species));
		}

		return false;
	}

}

12. 查找宠物猫信息

...
// 查找一: 在集合中查找花花的信息并输出
if (set.contains(huahua)) {
	System.out.println("花花找到了!");
	System.out.println(huahua);
} else {
	System.out.println("花花没找到!");
}


// 查找二: 在集合中根据名字查找花花的信息
boolean flag = false;
Cat c = null;
it = set.iterator();
while (it.hasNext()) {
	c = (Cat) it.next();
	if (c.getName().equals("花花")) {
		flag = true; // 找到了
		break;
	}
}
if (flag) {
	System.out.println("花花找到了");
	System.out.println(c);
}else {
	System.out.println("花花没找到");
}
...

13. 删除元素

泛型

  • jdk5.0 之后出来的,表示 后面的类型指定为某一个特定类型
例如 Set<Cat> set = new HashSet<Cat>();    类名后面的 <cat> 和构造方法后面的<cat> 都需要加. 

删除代码如下

// 增强型for循环
// 删除 花花二代的信息并重新输出
for (Cat cat : set) {
	if (cat.getName().equals("花花二代")) {
		set.remove(cat);
		break;
	}
}
System.out.println("删除花花二代后的数据");
// 输出元素
for (Cat cat : set) {
	System.out.println(cat);
}

// 删除集合中的所有宠物猫信息
System.out.println("************");
boolean flag1 = set.removeAll(set);
if (flag1) {
	System.out.println("删除成功!");
} else {
	System.out.println("猫还在!");
}

// 上面的 if(flag1) 也可以换成 if(set.isEmpty())

14. Map概述

  • Map 中的数据是以键值对(key-value) 的形式存储的
  • key-value 以 Entry 类型的对象实例存在
  • 可以通过key值快速的查找value
  • 一个映射不能包含重复的键
  • 每个键最多只能映射一个值

HashMap

  • 基于哈希表的Map接口的实现
  • 允许使用null值和null键
  • key值不允许重复
  • HashMap 中的 Entry对象是无序排列的

15. 案例:在字典中添加内容并显示

完成一个类似字典的功能

  • 将单词以及单词的注释存储到 HashMap 中
  • 显示 HashMap 中的内容
  • 查找某个单词的注释并显示

HashMap中常见方法

  • put(k,v) 添加数据

HashMap 添加数据,显示数据,查找数据 案例如下

package com.imooc.set1;

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

public class DictionaryDemo {

	public static void main(String[] args) {
		// 定义一个 HashMap的对象,来存储 字典的内容
		Map<String, String> animal = new HashMap<String, String>();
		System.out.println("请输入三组单词对应的注释, 并存放到HashMap中");
		Scanner console = new Scanner(System.in);
		// 添加数据
		int i = 0;
		while (i < 3) {
			System.out.println("请输入key的值(单词): ");
			String key = console.next();
			System.out.println("请输入value值(注释): ");
			String value = console.next();
			animal.put(key, value);
			i++;
		}

		System.out.println("*******************");
		// 打印输出value的值(直接使用迭代器完成)
		System.out.println("使用迭代器输出所有的value:");
		Iterator<String> it = animal.values().iterator(); // animal.values()返回的是一个集合. 再调用集合的iterator()迭代器方法
		while (it.hasNext()) {
			System.out.print(it.next() + " ");
		}

		System.out.println();
		System.out.println("*******************");
		// 打印输出key和value的值, 通过 entrySet方法
		System.out.println("通过entrySet方法得到key-value");
		Set<Entry<String, String>> entrySet = animal.entrySet();
		for (Entry<String, String> entry : entrySet) {
			System.out.print(entry.getKey() + "-");
			System.out.print(entry.getValue() + " ");
		}

		System.out.println();
		System.out.println("*******************");
		// 通过单词找到注释并输出, 使用 keySet方法
		String strSearch = console.next();
		// 1. 取得keySet()
		Set<String> keySet = animal.keySet();
		// 2. 遍历keySet()
		for (String key : keySet) {
			if (strSearch.equals(key)) {
				System.out.println("找到了!" + "键值对为: " + key + "-" + animal.get(key));
				break; 
			}
		}

	}

}


16. 商品信息管理

1. 商品信息管理需求

  • 使用 HashSet 对商品信息进行管理,其中 key为商品编号, value为商品对象.
  • 对HashMap中的商品信息进行增,删,改,查操作.

2. 分析商品信息类

2.1 属性

  • 商品编号: id
  • 商品名称: name
  • 商品价格: price

2.2 方法

  • 构造方法
  • 获取和设置属性值的方法
  • 其他方法

3. 代码实现, 先建Goods类,如下

package com.imooc.set1;

public class Goods {

	private int id; // 商品编号
	private String name; // 商品名称
	private int price; // 商品价格

	public Goods() {
	}

	public Goods(int id, String name, int price) {
		this.setId(id);
		this.setName(name);
		this.setPrice(price);
	}

	public int getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "商品编号: " + id + ", 商品名称: " + name + ",商品价格: " + price;
	}

}

17. 商品信息添加

如上,添加 GoodTest 类,测试添加信息, 显示信息

package com.imooc.set1;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;

public class GoodsTest {

	public static void main(String[] args) {
		Scanner console = new Scanner(System.in);
		// 定义HashMap对象
		Map<String, Goods> goodsMap = new HashMap<String, Goods>();
		System.out.println("请输入三条商品信息: ");
		int i = 0;
		while (i < 3) {
			System.out.println("请输入" + (i + 1) + "条商品信息:");
			System.out.println("请输入商品编号: ");
			String goodsId = console.next();
			System.out.println("请输入商品名称: ");
			String goodsName = console.next();
			System.out.println("请输入商品价格: ");
			double goodsPrice = console.nextDouble();

			Goods goods = new Goods(goodsId, goodsName, goodsPrice);
			// 将商品信息添加到 HashMap中
			goodsMap.put(goodsId, goods);
			i++;
		}

		// 遍历Map, 输出商品信息
		System.out.println("商品的全部信息为:");
		Iterator<Goods> itGoods = goodsMap.values().iterator();
		while (itGoods.hasNext()) {
			System.out.println(itGoods.next());
		}

	}

}

18. 商品信息添加优化

上述代码中,还有几点不完善

  1. 编号不能重复
String goodsId = console.next();
// 判断商品编号id是否存在
if(goodsMap.containsKey(goodsId)) {
	System.out.println("该商品编号已经存在! 请重新输入! ");
	continue;
}
  1. 输入商品价格的时候,如果输入字符的话,会报错.
double goodsPrice = 0;
try {
	goodsPrice = console.nextDouble();
} catch (java.util.InputMismatchException e) {
	System.out.println("商品价格的格式不正确,请输入数值型数据!");
	console.next(); //这里需要注意,需要加一个
	continue;
}

完整代码

package com.imooc.set1;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;

public class GoodsTest {

	public static void main(String[] args) {
		Scanner console = new Scanner(System.in);
		// 定义HashMap对象
		Map<String, Goods> goodsMap = new HashMap<String, Goods>();
		System.out.println("请输入三条商品信息: ");
		int i = 0;
		while (i < 3) {
			System.out.println("请输入" + (i + 1) + "条商品信息:");
			System.out.println("请输入商品编号: ");
			String goodsId = console.next();
			// 判断商品编号id是否存在
			if (goodsMap.containsKey(goodsId)) {
				System.out.println("该商品编号已经存在! 请重新输入! ");
				continue;
			}

			System.out.println("请输入商品名称: ");
			String goodsName = console.next();
			System.out.println("请输入商品价格: ");

			double goodsPrice = 0;
			try {
				goodsPrice = console.nextDouble();
			} catch (java.util.InputMismatchException e) {
				System.out.println("商品价格的格式不正确,请输入数值型数据!");
				console.next(); //这里需要注意,需要加一个
				continue;
			}

			Goods goods = new Goods(goodsId, goodsName, goodsPrice);
			// 将商品信息添加到 HashMap中
			goodsMap.put(goodsId, goods);
			i++;
		}

		// 遍历Map, 输出商品信息
		System.out.println("商品的全部信息为:");
		Iterator<Goods> itGoods = goodsMap.values().iterator();
		while (itGoods.hasNext()) {
			System.out.println(itGoods.next());
		}

	}
	

}


五. java线程

1. 什么是线程

进程的概念

  • 进程是指可执行程序并存放在计算机存储器的一个指令序列, 它是一个动态执行的过程.

什么是线程

  • 线程是比进程还要小的运行单位,一个进程包含多个线程, 线程可以看出一个子程序.

2. Thread和Runnable接口介绍

线程的创建,有2种方式

  1. 创建一个 Thread 类,或者一个 Thread 子类的对象
  2. 创建一个实现 Runnable 接口的类的对象
  • Thread 是一个线程类, 位于 java.lang 包下
构造方法说明
Thread()创建一个线程对象
Thread(String name)创建一个具有指定名称的线程对象
Thread(Runnable target)创建一个基于Runnable接口实现类的线程对象
Thread(Runnable target,String name)创建一个基于Runnable接口实现类,并且具有指定名称的线程对象.
  • Thread类 的常用方法
方法说明
public void run()线程相关的代码写在该方法中,一般需要重写
public void start()启动线程的方法
public static void sleep(long m)线程休眠m毫秒的方法
public void join()优先执行调用join()方法的线程

Runnable 接口

  • 只有一个方法 run();
  • Runnable 是 Java 中用以实现线程的接口
  • 任何实现线程功能的类都必须实现该接口

3. 通过Thread类创建线程

  • 通过继承 Thread类的方式创建线程类, 重写 run() 方法

案例

  1. 新建一个 MyThread 类继承自 Thread
package com.imooc.thread;

public class MyThread extends Thread {
	public void run() {
		System.out.println(getName() + "该线程正在执行!");
	}
}

  1. 新建一个测试类
package com.imooc.thread;

public class ThreadTest {

	public static void main(String[] args) {
		System.out.println("主线程1");

		MyThread mt = new MyThread();
		mt.start(); // 启动线程, 只能启动一次

		System.out.println("主线程2");

		/**
		 * 输出 
		 * 主线程1 
		 * 主线程2 
		 * Thread-0该线程正在执行!
		 * 
		 */
	}

}

4. 实现Runnable接口创建线程

  • 通过实现Runnable接口的方式创建.

为什么要实现Runnable接口

  1. Java不支持多继承
  2. 不打算重写 Thread 类的其他方法

实现Runnable接口创建线程步骤有三

  1. 创建 Runnable类的实现对象
  2. 创建 Thread类的对象
  3. 启动线程

代码如下

package com.imooc.runnable;

class PrintRunnable implements Runnable {

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + "正在运行!");

	}

}

public class Test {

	public static void main(String[] args) {
		// 1 创建 Runnable类的实现对象
		PrintRunnable pr1 = new PrintRunnable();
		// 2 创建 Thread类的对象
		Thread t1 = new Thread(pr1);
		// 3 启动线程
		t1.start();

		// 创建 Runnable类的实现对象
		PrintRunnable pr2 = new PrintRunnable();
		// 创建 Thread类的对象
		Thread t2 = new Thread(pr2);
		// 启动线程
		t2.start();

	}

}

5. 线程的状态和生命周期

线程状态

  • 新建(New)
  • 可运行(Runnable) / 也叫 就绪状态
  • 正在运行(Running)
  • 阻塞(Blocked)
  • 终止(Dead)

线程的生命周期

在这里插入图片描述

6. sleep方法的使用

  • sleep方法是 Thread类的方法

public static void sleep(long millis)

  • sleep方法的作用: 在指定的毫秒数内让正在执行的线程休眠(暂停执行)
  • 参数为休眠的时间,单位是毫秒
package com.imooc.sleep;

class MyThread implements Runnable {

	@Override
	public void run() {
		for (int i = 1; i <= 30; i++) {
			System.out.println(Thread.currentThread().getName() + "执行第" + i + "次!");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

public class SleepDemo {

	public static void main(String[] args) {
		MyThread mt = new MyThread();
		Thread t = new Thread(mt);
		t.start();
		
		MyThread mt1 = new MyThread();
		Thread t1 = new Thread(mt1);
		t1.start();
	}

}

7. join方法的使用

  • join方法 也是 Thread类的方法

public final void join()

  • join方法的作用: 等待调用该方法的线程结束后才能执行 (调用了join()方法的线程优先执行,执行完才轮到其他线程执行.)

public final void join(long millis)

  • 上述作用: 等待该线程终止的最长时间为 millis 毫秒.

例子如下

package com.imooc.join;

class MyThread extends Thread {
	public void run() {
		System.out.println(getName() + "正在执行!");
	}
}

public class JoinDemo {

	public static void main(String[] args) {
		MyThread mt = new MyThread();
		mt.start();
		try {
			mt.join(); // 抢占资源,优先执行
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("主线程运行结束!");
	}

	/**
	 * 输出 Thread-0正在执行! 
	 * 主线程运行结束!
	 * 
	 */

}

8. 线程的优先级

  • Java 为线程提供了 10个优先级,数字越大,优先级越高.

  • 优先级可以用整数 1-10 表示,超出范围会抛出异常.

  • 主线程默认优先级为5.

  • 除了使用 数字来表示线程的优先级,还可以用 优先级常量来表示.

  • MAX_PRIORITY: 线程的最高优先级 10

  • MIN_PRIORITY: 线程的最低优先级 1

  • NORM_PRIORITY: 线程的默认优先级 5

优先级相关的方法

方法说明
public int getPriority()获取线程优先级的方法
public void setPriority(int newPriority)设置线程优先级的方法

案例

package com.imooc.priority;

class MyThread extends Thread {
	private String name;

	public MyThread(String name) {
		this.name = name;
	}

	public void run() {
		for (int i = 0; i <= 50; i++) {
			System.out.println("线程" + name + "正在运行" + i);
		}
	}
}

public class Priority {
	public static void main(String[] args) {
		// 获取主线程的优先级
		// Thread.currentThread() 表示当前线程
		int mainPriority = Thread.currentThread().getPriority();
		System.out.println("主线程的优先级为: " + mainPriority);
		// 自定义线程
		MyThread mt1 = new MyThread("线程一");
//		mt1.setPriority(10);
		mt1.setPriority(Thread.MAX_PRIORITY);
		mt1.start();

		MyThread mt2 = new MyThread("线程二");
		mt2.setPriority(Thread.MIN_PRIORITY);
		mt2.start();

		System.out.println("线程一的优先级为: " + mt1.getPriority());
		System.out.println("线程二的优先级为: " + mt2.getPriority());
	}
}

9. 线程同步

多线程运行问题

  1. 各个线程是通过竞争cpu时间而获得运行机会的.
  2. 各线程什么时候得到CPU时间,占用多久,是不可预测的.
  3. 一个正在运行着的线程在什么地方被暂停是不确定的.

银行存取款问题

  • 为了保证在存款或取款的时候, 不允许其他线程对账户余额进行操作.
  • 需要将 Bank 对象进行锁定.
  • 使用同步关键字 synchronized 实现 对 Bank 对象的锁定.

synchronized关键字用在

  • 成员方法
  • 静态方法
  • 语句块

public synchronized void saveAccount(){…}
public static synchronized void saveAccount() {…}
synchronized (obj){…}

案例源码

  1. Bank 类
package com.imooc.bank;

public class Bank {

	private String account; // 账号
	private int balance; // 余额

	public Bank() {
	}

	public Bank(String account, int balance) {
		this.setAccount(account);
		this.setBalance(balance);
	}

	public String getAccount() {
		return this.account;
	}

	public void setAccount(String account) {
		this.account = account;
	}

	public int getBalance() {
		return this.balance;
	}

	public void setBalance(int balance) {
		this.balance = balance;
	}

	@Override
	public String toString() {
		return "Bank [账号: " + this.account + ",余额: " + balance + "]";
	}

	// 存款
	public synchronized void saveAccount() {
		// 可以在不同的位置处添加 sleep 方法
		// 获取当前的账户余额
		int balance = this.getBalance();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 修改余额, 寸100元
		balance += 100;
		// 修改账户余额
		this.setBalance(balance);
		// 输出存款后的账户余额
		System.out.println("存款后的账户余额为: " + balance);
	}

	// 取款
	public void drawAccount() {
		// synchronized的另外一种使用方法
		synchronized (this) {
			// 在不同的位置处添加sleep方法
			// 获取当前的账户余额
			int balance = getBalance();
			// 修改余额, 取200
			balance = balance - 200;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			// 修改账户余额
			this.setBalance(balance);
			System.out.println("取款后的账户余额: " + balance);
		}
	}

}

  1. 存款类 SaveAccount
package com.imooc.bank;

public class SaveAccount implements Runnable {

	Bank bank;

	public SaveAccount(Bank bank) {
		this.bank = bank;
	}

	@Override
	public void run() {
		bank.saveAccount();

	}

}

  1. 取款类 DrawAccount
package com.imooc.bank;

public class DrawAccount implements Runnable {
	Bank bank;

	public DrawAccount(Bank bank) {
		this.bank = bank;
	}

	@Override
	public void run() {
		bank.drawAccount();
	}

}

  1. 代码测试类 Test
package com.imooc.bank;

public class Test {

	public static void main(String[] args) {
		// 创建账户,给定余额1000
		Bank bank = new Bank("1001", 1000);
		// 创建线程对象
		SaveAccount sa = new SaveAccount(bank);
		DrawAccount da = new DrawAccount(bank);
		Thread save = new Thread(sa);
		Thread draw = new Thread(da);
		save.start();
		draw.start();

		try {
			draw.join();
			save.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println(bank);

	}

	/**
	 * 输出 存款后的账户余额为: 1100 
	 * 取款后的账户余额: 900 
	 * Bank [账号: 1001,余额: 900]
	 * 
	 */

}

10. 线程间通信

  • 如上述 银行存取款的案例, 那么 如果账户余额不够了怎么办?
  • 等待存入足够的钱后处理.

线程间通信

  • wait() 方法: 中断方法的执行, 使线程等待.
  • notify() 方法: 唤醒处于等待的某一个线程, 使其结束等待.
  • notifyAll() 方法: 唤醒所有处于等待的线程, 使它们结束等待.

案例

  1. Queue类
package com.imooc.queue;

public class Queue {

	private int n;
	boolean flag = false;

	public Queue() {
	}

	public synchronized int getN() {
		if (!flag) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("消费: " + this.n);
		flag = false; // 消费完毕,容器中没有数据
		notifyAll();
		return n;
	}

	public synchronized void setN(int n) {
		if (flag) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("生产: " + n);
		this.n = n;
		flag = true; // 生成完毕, 容器中已经有数据
		notifyAll();
	}

}

  1. 生产者类 Producer
package com.imooc.queue;

public class Producer implements Runnable {

	Queue queue;

	public Producer() {
	}

	public Producer(Queue queue) {
		this.queue = queue;
	}

	@Override
	public void run() {
		int i = 0;
		while (true) {
			queue.setN(i++);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

  1. 消费者类
package com.imooc.queue;

public class Consumer implements Runnable {

	Queue queue;

	public Consumer() {
	}

	public Consumer(Queue queue) {
		this.queue = queue;
	}

	@Override
	public void run() {
		while (true) {
			queue.getN();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

  1. 测试类 Test
package com.imooc.queue;

public class Test {

	public static void main(String[] args) {
		Queue queue = new Queue();
		new Thread(new Producer(queue)).start();
		new Thread(new Consumer(queue)).start();
	}

}


六. java输入流

1. 概述

  • 输出流 write(写操作)
    在这里插入图片描述

  • 输入流 read(读操作)
    在这里插入图片描述

2. File类

什么是文件?

  • 文件可认为是相关记录或放在一起的数据的集合.
  • 在 Java 中,使用 java.io.File 类对文件进行操作.

3. File类的常用方法

  1. 创建 File 对象的几种方法
  • 方式一, 直接写路径
File file1 = new File("/Users/zhangqiang/Desktop/demo/io/score.txt");

注意: 环境是 mac, 如果是windows系统 路径应该是 new File(“c:\\imooc\\set\\HashSet”)

  • 方式二, 把路径拆分写
File file1 = new File("/Users/zhangqiang/Desktop/demo", "io/score.txt");
  • 方式三, 父路径作为第一个对象,然后在父对象上,再申明一个对象
File file = new File("/Users/zhangqiang/Desktop/");
File file1 = new File(file, "demo/io/score.txt");
  1. 判断是文件还是目录
// 判断是文件还是目录
System.out.println("是否是目录: " + file1.isDirectory()); // false
System.out.println("是否是文件: " + file1.isFile()); // true
  1. 创建目录 mkdir()创建单级目录, mkdirs()创建多级目录
//创建目录, 单级目录 mkdir()
File file2 = new File("/Users/zhangqiang/Desktop/demo/set/", "HashSet");
if(!file2.exists()) {
	file2.mkdir();
}

//创建目录, 多级目录 mkdirs()
File file3 = new File("/Users/zhangqiang/Desktop/demo/set/", "HashSet/test");
if(!file3.exists()) {
	file3.mkdirs();
}
  1. 创建文件 createNewFile()
//创建文件
if(!file1.exists()) {
	try {
		file1.createNewFile();
	} catch (IOException e) {
		e.printStackTrace();
	}
}

完整示例

package com.imooc.file;

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

public class FileDemo {

	public static void main(String[] args) {
		/**
		 *  创建一个 File 对象, 方式一, 直接写路径
		 *  File file1 = new File("/Users/zhangqiang/Desktop/demo/io/score.txt");
		 */
		
		/**
		 *  创建一个 File 对象, 方式二, 把路径拆分写
		 *  File file1 = new File("/Users/zhangqiang/Desktop/demo", "io/score.txt");
		 *
		 */
		
		/**
		 *  创建一个 File 对象, 方式三, 父路径作为第一个对象,然后在父对象上,再申明一个对象
		 *  
		 */
		File file = new File("/Users/zhangqiang/Desktop/");
		File file1 = new File(file, "demo/io/score.txt");
		

		// 判断是文件还是目录
		System.out.println("是否是目录: " + file1.isDirectory()); // false
		System.out.println("是否是文件: " + file1.isFile()); // true
		
		//创建目录, 单级目录 mkdir()
		File file2 = new File("/Users/zhangqiang/Desktop/demo/set/", "HashSet");
		if(!file2.exists()) {
			file2.mkdir();
		}
		
		//创建目录, 多级目录 mkdirs()
		File file3 = new File("/Users/zhangqiang/Desktop/demo/set/", "HashSet/test");
		if(!file3.exists()) {
			file3.mkdirs();
		}
		
		//创建文件
		if(!file1.exists()) {
			try {
				file1.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		
		

	}

}

4. 字节流概述

字节流是单个字节的操作,一般用于2进制中

  • 字节输入流 InputStream
  • 字节输出流 OutputStream

在这里插入图片描述
在这里插入图片描述

5. FileIntputStream

  • 文件输入流 是从文件系统中的某个文件获得输入字节
  • 用于读取诸如图像数据之类的原始字节流
方法名说明
public int read()从输入流中读取一个数据字节
public int read(byte[] b)从输入流中将最多 b.length 个字节的数据读入一个 byte 数组中
public int read(byte[] b, int off, int len)从输入流中将最多 len 个字节的数据读入 byte 数组中
public void close()关闭此文件输入流并释放与此流有关的所有系统资源
  • read() 方法, 如果返回值为 -1, 则表示已经达到文件末尾!

6. FileIntputStream 例子

  • 读txt中的内容
package com.imooc.file;

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

public class FileInputDemo1 {

	public static void main(String[] args) {
		// 创建一个 FileInputStream 对象
		try {
			FileInputStream fis = new FileInputStream("imooc.txt");

			/**
			 * 读取文件中的内容, 常规写法一
			 */
			int n = fis.read(); // 读取一个字符
			while (n != -1) {
				System.out.print((char) n);
				n = fis.read();
			}

			/**
			 * 读取文件中的内容, 简写二 
			 * while ((n = fis.read()) != -1) { 
			 * 		System.out.println((char)n); \
			 * }
			 */

			fis.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

  • 把文件中的内容放到 byte数组中,然后输出
package com.imooc.file;

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

public class FileInputDemo2 {
	public static void main(String[] args) {
		// 创建一个 FileInputStream 对象
		try {
			FileInputStream fis = new FileInputStream("imooc.txt");

			// 把 txt中的内容放到 字节数组中
			byte[] b = new byte[100];
			fis.read(b);
			System.out.println(new String(b));

			fis.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}

7. FileOutputStrwam

常用方法

方法名描述
public void write(int b)将指定字节写入此文件输出流
public void write(byte[] b)将 b.length 个字节从指定 byte 数组写入此文件输出流中
public void write(byte[] b, int off, int len)将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流
public void close()关闭此文件输出流并释放与此流有关的所有系统资源
package com.imooc.file;

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

public class FileOutputDemo {

	public static void main(String[] args) {
		FileOutputStream fos;
		FileInputStream fis;

		try {
			fos = new FileOutputStream("imooc.txt", true);
			fis = new FileInputStream("imooc.txt");

			fos.write(50);
			fos.write('a');

			System.out.println(fis.read());
			System.out.println((char) fis.read());

			fos.close();
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}


文件拷贝

package com.imooc.file;

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

public class FileOutputDemo1 {

	public static void main(String[] args) {
		// 文件拷贝
		try {
			// 输入流对象, 把文件读到字节中
			FileInputStream fis = new FileInputStream("01.jpg");

			// 输出流对象, 把字节写到文件中
			FileOutputStream fos = new FileOutputStream("01copy.jpg");

			int n = 0;
			byte[] b = new byte[1024];

			while ((n = fis.read(b)) != -1) {
				fos.write(b, 0, n);
			}

			fis.close();
			fos.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

8. 缓冲流概述

缓冲流可以提升速度

  • 缓冲输入流 BufferedInputStream
  • 缓冲输出流 BufferedOutputStream

9. 缓冲流案例

package com.imooc.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedDemo {

	public static void main(String[] args) {
		try {
			FileOutputStream fos = new FileOutputStream("imooc.txt");
			BufferedOutputStream bos = new BufferedOutputStream(fos);
			FileInputStream fis = new FileInputStream("imooc.txt");
			BufferedInputStream bis = new BufferedInputStream(fis);

			// 开始时间, 长整型
			long startTime = System.currentTimeMillis();

			bos.write(50);
			bos.write('a');
			bos.flush();

			// 结束时间,长整型
			long endTime = System.currentTimeMillis();
			// 计算时间差
			System.out.println(endTime - startTime);

			System.out.println(bis.read());
			System.out.println((char) bis.read());

			fos.close();
			bos.close();
			fis.close();
			bis.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

PS: 计算程序运行时间

// 开始时间, 长整型
long startTime = System.currentTimeMillis();

// ...

// 结束时间,长整型
long endTime = System.currentTimeMillis();
// 计算时间差
System.out.println(endTime - startTime);

10. 字符流概述

  • 字符输入流 Reader
  • 字符输出流 Writer

在这里插入图片描述
在这里插入图片描述

11. 字节字符转换流

  • InputStreamReader
  • OutputStreamWriter
package com.imooc.file;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class charstream {

	public static void main(String[] args) {

		try {
			FileInputStream fis = new FileInputStream("imooc.txt");
			InputStreamReader isr = new InputStreamReader(fis, "UTF8");

			FileOutputStream fos = new FileOutputStream("imooc1.txt");
			OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");

			// 读取数据
			int n = 0;
			char[] cbuf = new char[10];
//			while ((n = isr.read()) != -1) {
//				System.out.print((char) n);
//			}

//			while ((n = isr.read(cbuf)) != -1) {
//				String s = new String(cbuf, 0, n);
//				System.out.print(s);
//			}

			while ((n = isr.read(cbuf)) != -1) {
				osw.write(cbuf, 0, n);
				osw.flush();
			}

			fis.close();
			fos.close();
			isr.close();
			osw.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

12. 其他字符流

  • BufferedReader
  • BufferedWrite
package com.imooc.file;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class charstream {

	public static void main(String[] args) {

		try {
			// 字节流
			FileInputStream fis = new FileInputStream("imooc.txt");
			// 字符流
			InputStreamReader isr = new InputStreamReader(fis, "UTF8");
			// 字符缓冲流
			BufferedReader br = new BufferedReader(isr);

			FileOutputStream fos = new FileOutputStream("imooc1.txt");
			OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");
			BufferedWriter bw = new BufferedWriter(osw);

			// 读取数据
			int n = 0;
			char[] cbuf = new char[10];
//			while ((n = isr.read()) != -1) {
//				System.out.print((char) n);
//			}

//			while ((n = isr.read(cbuf)) != -1) {
//				String s = new String(cbuf, 0, n);
//				System.out.print(s);
//			}

			while ((n = br.read(cbuf)) != -1) {
				bw.write(cbuf, 0, n);
				bw.flush();
			}

			fis.close();
			fos.close();
			isr.close();
			osw.close();
			br.close();
			bw.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

13. 对象的序列化与反序列化

  • 序列化: 把 Java对象转换为字节序列的过程.
  • 反序列化: 把字节序列恢复为 Java 对象的过程.

对象序列化步骤:

  1. 创建一个类, 继承 Serializable 接口
  2. 创建对象
  3. 将对象写入文件
  4. 从文件读取对象信息

对象序列化涉及到2个类

  • 对象输入流 ObjectInputStream
  • 对象输出流 ObjectOutputStream
package com.imooc.serial;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class GoodsTest {

	public static void main(String[] args) {
		// 定义Goods类对象
		Goods goods1 = new Goods("gd001", 3000, "电脑");
		try {
			// 写数据, 将对象信息写入文件
			FileOutputStream fos = new FileOutputStream("imooc.txt");
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(goods1);
			oos.flush();

			// 读数据, 读Goods对象的信息
			FileInputStream fis = new FileInputStream("imooc.txt");
			ObjectInputStream ois = new ObjectInputStream(fis);
			try {
				Goods goods = (Goods) ois.readObject();
				System.out.println(goods);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}

			fos.close();
			oos.close();
			fis.close();
			ois.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}


七. java常用工具类综合练习

1. 课程概述及需求分析

2. 效果演示

3. 详细设计


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值