目录
第四章 Java异常处理
1、异常的概念
2、捕获和处理异常:
3、throws和throw关键字
4、Exception和RunTimeException的区别
第五章 Java常用类
1、Java日期处理类
2、String与StringBuffer
3、Math类
第六章 泛型
1、泛型引入
2、限制泛型
3、通配符泛型
4、泛型方法
第七章 Java集合
1、Java集合的引入
第八章 Java多线程
1、多线程的引入:同时对多项任务加以控制
2、多线程的实现:
3、线程的状态
4、线程的常用方法
5、线程同步机制:
异常指程序运行过程中出现的非正常现象
try ..catch
try ..catch finally
public static void main(String[] args) {
String str="123ad";
int a = Integer.parseInt(str);//这个强制转换会出错
System.out.println(a);
}
Exception in thread "main" java.lang.NumberFormatException: For input string: "123ad"
可以看到,能写多个catch,范围从小到大,可以排查异常原因
public static void main(String[] args) {
String str="123ad";
try{
int a = Integer.parseInt(str);
}catch(ArithmeticException e){//出现了数学异常
e.printStackTrace();
}catch(ArrayIndexOutOfBoundsException e){//出现了数组异常
e.printStackTrace();
}catch (NumberFormatException e){//格式异常
e.printStackTrace();//打印栈信息
}catch (Exception e){//其他异常
e.printStackTrace();
}
//捕获异常后,后面的代码还可以执行
System.out.println("aa");
}
finally的用法也是面试常问的问题,finally是一定要执行的,哪怕之前加了return
public class Demo2 {
public static void testFinally(){
String str="123a";
try{
int a = Integer.parseInt(str);
System.out.println(a);
}catch(Exception e){
e.printStackTrace();
System.out.println("Exception");
return; //加了return,执行完finally就返回
}finally{ //finally是一定要执行到的
System.out.println("final end");
}
System.out.println("end");
}
public static void main(String[] args) {
testFinally();
}
}
throws表示当前方法不处理异常,而是交给方法的调用处去处理
throw表示直接抛出一个异常
区别:throws是检测代码是否有异常,代码异常才会抛出异常。throws用来抛出异常,不管代码本身是不是有异常。
throws用于方法声明后,throw用于方法体内
//throws
public class Demo1 {
public static void testThrows() throws NumberFormatException{
String str="123ad";
int a = Integer.parseInt(str);
System.out.println(a);
}
public static void main(String[] args) {
try{
testThrows(); //在这里调用
System.out.println("here");
}catch(Exception e){
e.printStackTrace();
System.out.println("我们在这里处理异常");
}
}
}
可以看到下面这段代码是没异常的,但使用了throw后会抛出异常。还有throws用于方法声明后,throw用于方法体内
//throw
public class Demo2 {
public static void testThrow(int a)throws Exception{
if(a==1){
throw new Exception("有异常");
}
System.out.println(a);
}
public static void main(String[] args) {
try{
testThrow(1);
}catch(Exception e){
e.printStackTrace();
}
try{
testThrow(0);
}catch(Exception e){
e.printStackTrace();
}
}
}
Exception是检查型异常,编译时会检查,在程序中必须使用try..catch进行处理
RunTimeException是非检查型异常,可不用try..catch进行处理(最好用),但是如果产生异常,则异常将由JVM进行处理
public class Demo1 {
//NumberFormatException继承自RunTimeException
public static void testThrows() throws NumberFormatException{
String str="123ad";
int a = Integer.parseInt(str);
System.out.println(a);
}
public static void main(String[] args) {
testThrows();//编译时不检查,运行时异常
System.out.println("能运行吗?");//不能继续运行,最好还是捕获
}
5、自定义异常(自己定义一个处理异常的类)
所有异常都必须是 Throwable 的子类。
如果希望写一个检查性异常类,则需要继承 Exception 类。
如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
1)Data类
import java.util.Date;
public class testData {
public static void main(String[] args) {
Date date = new Date();
System.out.println("当前日期:"+date);
}
}
当前日期:Mon Mar 09 22:14:31 CST 2020
2)Calendar类
import java.util.Calendar;
public class testCalendar {
public static void main(String[] args) {
//创建实例,不能new,Calendar构造方法是protected,子类才能new
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.get(Calendar.YEAR));//获取年
System.out.println(calendar.get(Calendar.MONTH)+1);//获取月,从0开始
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//日
System.out.println(calendar.get(Calendar.HOUR_OF_DAY));//时
System.out.println(calendar.get(Calendar.MINUTE));//分
System.out.println(calendar.get(Calendar.SECOND));//秒
}
}
3)SimpleDataFormat:以于语言环境有关的方式来格式化或解析日期的具体类
格式化:日期->文本
解析:文本->日期
和规范化
//日期——>文本
package com.java.chap05.sec1;
import java.text.SimpleDateFormat;
import java.util.Date;
public class testSimpleDataFormat {
public static void main(String[] args) {
Date date = new Date();
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
System.out.println(sdf.format(date));//format返回一个String,把日期格式化为文本
}
}
2020-29-11 21:29:15
//日期——>文本
public class testSimpleDataFormat2 {
/**
* 进行方法包装
* @param date 日期
* @param format 格式
* @return
*/
public static String dateFormat(Date date,String format){
String result = "";
SimpleDateFormat sdf = new SimpleDateFormat(format);
if (date!=null){
result = sdf.format(date);
}
return result;
}
public static void main(String[] args) {
Date date = new Date();
System.out.println(dateFormat(date,"yyyy-MM-dd"));
System.out.println(dateFormat(date,"yyyy-MM-dd HH:mm:ss"));
}
}
2020-03-11
2020-03-11 21:45:13
public class testSimpleDataFormat2 {
/**
* 格式化日期:日期——> 字符串
* @param date 日期对象
* @param format 格式
* @return
*/
public static String dateFormat(Date date,String format){
String result = "";
SimpleDateFormat sdf = new SimpleDateFormat(format);
if (date!=null){
result = sdf.format(date);
}
return result;
}
/**
* 解析:日期字符串->日期对象
* @param dateStr 日期字符串
* @param format 格式
* @return
* @throws ParseException
*/
public static Date dateFormat(String dateStr,String format) throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.parse(dateStr);
}
public static void main(String[] args) throws ParseException {
Date date = new Date();
System.out.println(dateFormat(date,"yyyy-MM-dd"));//日期转文本
System.out.println(dateFormat(date,"yyyy-MM-dd HH:mm:ss"));//日期转文本
String dateStr = "2033-01-22";
Date date2 = dateFormat(dateStr,"yyyy-MM-dd");//文本转日期
System.out.println(date2);
System.out.println(dateFormat(date2,"yyyy-MM-dd"));//日期转文本
}
}
2020-03-11
2020-03-11 22:21:43
Sat Jan 22 00:00:00 CST 2033
2033-01-22
1)对String类型的对象进行操作,等同于重新生成一个对象,然后引用指向他。(字符串内容不可变性)
public static void main(String[] args) {
String str = "123";
str+="abc";
System.out.println(str);
}
123abc
2) 对StringBuffer类型的对象进行操作,操作的始终是一个对象。
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("123");
sb.append("abc");//append拼接
System.out.println(sb);
}
max最大值
min最小值
round:四舍五入
round(double a):返回最接近参数的long
round(fioat a):返回最接近参数的int
pow:求次幂
sqrt:求平方根
public static void main(String[] args) {
System.out.println("最大值:"+Math.max(1, 5));
System.out.println("最小值:"+Math.min(8, 2));
System.out.println("四舍五入:"+Math.round(12.6));
System.out.println("四舍五入:"+Math.round(12.3));
System.out.println("3的四次方:"+Math.pow(3, 4));
System.out.println("求平方根:"+Math.sqrt(9));
}
最小值:2
四舍五入:13
四舍五入:12
3的四次方:81.0
求平方根:3.0
4、Arrys类
toString():arr变成String类型,可以直接输出了
sort():排序
binarySearch():二分查找,必须是已经排序好的,返回所在位置
fill():将指定类型值分配给指定类型数组的每个元素
package com.java.chap05.sec4;
import java.util.Arrays;
public abstract class Test {
public static void main(String[] args) {
int arr[]={1,8,5,3};
System.out.println("直接输出数组会出错"+arr);
System.out.println("字符串输出"+Arrays.toString(arr));
Arrays.sort(arr);
System.out.println("排序"+Arrays.toString(arr));
int s = Arrays.binarySearch(arr, 3);//返回所在位置
System.out.println("二分查找"+s);
Arrays.fill(arr, 0);//将指定内容填充到数组中
System.out.println("填充"+Arrays.toString(arr));
}
}
直接输出数组会出错[I@de6ced
字符串输出[1, 8, 5, 3]
排序[1, 3, 5, 8]
二分查找1
填充[0, 0, 0, 0]
(泛型可以指代任何对象类型)
public class C1 {
private Integer a;
public Integer getA() {
return a;
}
public void setA(Integer a) {
this.a = a;
}
public C1(Integer a) {
super();
this.a = a;
}
/*
* 打印a的类型
*/
public void print(){
System.out.println("a的数据类型是"+a.getClass().getName());
}
}
public class C2 {
private String a;
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public C2(String a) {
super();
this.a = a;
}
/*
* 打印a的类型
*/
public void print(){
System.out.println("a的数据类型是"+a.getClass().getName());
}
}
public class C12 {
private Object object;//Object是所有类的父类
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public C12(Object object) {
super();
this.object = object;
}
/*
* 打印object的类型
*/
public void print(){
System.out.println("object的数据类型是"+object.getClass().getName());
}
}
/**
* 定义泛型类
* @author xiaoqing
*/
public class CC {
private T ob;
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public CC(T ob) {
super();
this.ob = ob;
}
/*打印ob的实际类型*/
public void print() {
System.out.println("T的实际类型是"+ob.getClass().getName());
}
}
//测试
public class Test {
public static void main(String[] args) {
//test C1
C1 c1 = new C1(1);
c1.print();
int i = c1.getA();
System.out.println("i="+i);
//test C2
C2 c2 = new C2("Hi");
c2.print();
String str = c2.getA();
System.out.println("str="+str);
//test C12
C12 c12 = new C12("Hi");//向上转型
c12.print();
String ob = (String) c12.getObject();//向下转型
System.out.println("ob="+ob);
C12 c122 = new C12(2);//向上转型
c122.print();
int ob2 = (Integer) c122.getObject();//向下转型
System.out.println("ob2="+ob2);
//test CC
CC cc= new CC(1);
cc.print();
int ic = cc.getOb();
System.out.println("ic="+ic);
CC cc2 = new CC("我是泛型");
cc.print();
String ic2 = cc2.getOb();
System.out.println("ic2="+ic2);
}
}
a的数据类型是java.lang.Integer
i=1
a的数据类型是java.lang.String
str=Hi
object的数据类型是java.lang.String
ob=Hi
object的数据类型是java.lang.Integer
ob2=2
T的实际类型是java.lang.Integer
ic=1
T的实际类型是java.lang.String
ic2=我是泛型
public class Animals {
public void print(){
System.out.println("动物");
}
}
public void print(){
System.out.println("Dog");
}
public class Cat extends Animals{
public void print(){
System.out.println("Cat");
}
}
public class Demo {
private T ob;
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public Demo(T ob) {
super();
this.ob = ob;
}
public void print(){
System.out.println("T的数据类型是"+ob.getClass().getName());
}
}
public class Test {
public static void main(String[] args) {
Demo demo = new Demo(new Dog());
//CC cc= new CC(1);作为比对
Dog dog = demo.getOb();
dog.print();
Demo demo2 = new Demo(new Cat());
Cat cat = demo2.getOb();
cat.print();
Demo demo3 = new Demo(new Animals());
Animals animals = demo3.getOb();
animals.print();
//Demo demo4 = new Demo(new Integer()); 报错
}
}
Dog
Cat
动物
(只存放对象,且存的是对象的引用。如果int型的一些数据想用集合,就得装箱成Integer)
Set(集)、List(列表)和Map(映射)
2、List集合:继承自collection,有序,允许重复
1) LinkedList:LinkedList是一个实现了List接口和Deque接口的双向链表。
public boolean add(Object element) 向链表末尾添加一个新节点
public void add(int index,Object element) 向链表指定位置添加一个新节点
public Object remove(int index) 删除指定位置的节点
public Object get(int index) 得到指定位置的节点
int indexOf(Object element) 返回节点对象element在链表中首次出现的位置
public int lastIndexOf(Object element) 返回节点对象element在链表中最后出现的位置,
public Object set(int index,Object element) 将当前链表index位置节点中的对象替换成参数element指定的对象,返回被替换对象
public boolean contains(Object element) 判断链表节点对象中是否含有element
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;
}
}
import java.util.LinkedList;
public class Demo {
public static void main(String[] args) {
Student student[] = new Student[1];
Student s1 = new Student("张三",22);
Student s2 = new Student("李四",22);
LinkedList list = new LinkedList();
list.add(s1);
list.add(s2);
//集合遍历
for(int i = 0;i
2)ArrayList :
public class TestArrayList {
public static void print(ArrayList arrayList){
for(int i=0;i arrayList = new ArrayList();
//添加元素
arrayList.add("张三");
arrayList.add("李四");
//在指定位置添加元素
arrayList.add(1,"王五");
print(arrayList);
//替换
arrayList.set(1, "大象");
print(arrayList);
}
}
3、集合的遍历
1) Iteractor:迭代
public class TestIterator {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add(new Student("张三",21));
list.add(new Student("李四",22));
list.add(new Student("王五",22));
Iterator it = list.iterator();//返回一个迭代器
while(it.hasNext()){
Student s = it.next();//返回迭代的下一个元素
System.out.println("姓名:"+s.getName()+" 年龄"+s.getAge());
}
}
}
姓名:张三 年龄21
姓名:李四 年龄22
姓名:王五 年龄22
2) foreach
public class testForeach {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add(new Student("张三",21));
list.add(new Student("李四",22));
list.add(new Student("王五",22));
for(Student s:list){//每次取出一个对象
System.out.println("姓名:"+s.getName()+" 年龄:"+s.getAge());
}
}
}
姓名:张三 年龄:21
姓名:李四 年龄:22
姓名:王五 年龄:22
4、Set集合·:无序,不允许重复内容
1)hashSet
public class testHashSet {
public static void main(String[] args) {
/*
* 1、无序
* 2、不可重复
*/
HashSet hs = new HashSet();
hs.add("1");
hs.add("2");
hs.add("3");
hs.add("4");
hs.add("3");
for(String s:hs){
System.out.print(s);
}
}
}
3214
5、Map集合:接口中每个元素都是一对,以key->value键值对形式保存
1)HashMap
package com.java.chap07.sec5;
import java.util.HashMap;
import java.util.Iterator;
import com.java.chap07.sec1.Student;
public class testHashMap {
public static void main(String[] args) {
HashMap hm = new HashMap();
hm.put("1号", new Student("张三",10));
hm.put("2号", new Student("李四",20));
hm.put("3号", new Student("王五",30));
//通过key,获取value
Student s = hm.get("1号");
System.out.println("姓名:"+s.getName()+" 年龄"+s.getAge());
//遍历
Iterator it = hm.keySet().iterator();//获取key集合,再获取迭代器
while(it.hasNext()){
String key = it.next();//获取key
Student student = hm.get(key);//通过key,获取value
System.out.println("key:"+key+",value:"+student.getName()+student.getAge());
}
}
}
姓名:张三 年龄10
key:2号,value:李四20
key:3号,value:王五30
key:1号,value:张三10
public class Eat extends Thread{
@Override
public void run() {//实现run方法
for(int i = 0;i<3;i++){
try {
Thread.sleep(100);
System.out.println("吃饭");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class Music extends Thread{
@Override
public void run() {//实现run方法
for(int i = 0;i<3;i++){
try {
Thread.sleep(100);//延迟一下
System.out.println("听音乐");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class Demo {
public static void main(String[] args) {
/*eat();
music();*/
Music musicThread = new Music();
Eat eatThread = new Eat();
musicThread.start();
eatThread.start();
}
}
吃饭
听音乐
听音乐
吃饭
听音乐
吃饭
1)继承Thread
public class Thread1 extends Thread{
private int baozi=1;
private String threadName;
public Thread1(String threadName) {
super();
this.threadName = threadName;
}
@Override
public void run() {
while(baozi<=4){
System.out.println(threadName+"吃第"+baozi+"个包子");
baozi++;
}
}
public static void main(String[] args) {
Thread1 t1 = new Thread1("张三");
Thread1 t2 = new Thread1("李四");
t1.start();//实现run
t2.start();
}
}
张三吃第1个包子
李四吃第1个包子
李四吃第2个包子
张三吃第2个包子
张三吃第3个包子
张三吃第4个包子
李四吃第3个包子
李四吃第4个包子
2)实现Runnable接口
public class Thread2 implements Runnable{
private int baozi=1;
private String threadName;
public Thread2(String threadName) {
super();
this.threadName = threadName;
}
@Override
public void run() {
while(baozi<=4){
System.out.println(threadName+"吃第"+baozi+"个包子");
baozi++;
}
}
public static void main(String[] args) {
Thread2 t1 = new Thread2("张三");
Thread2 t2 = new Thread2("李四");
Thread tt1 = new Thread(t1);
Thread tt2 = new Thread(t2);
tt1.start();
tt2.start();
}
}
run():新建
start():就绪
getName():返回该线程的名称
currentThread():返回当前正在执行的线程对象的引用
isAlive():测试线程是否处于活动状态(从就绪)
sleep():线程休眠
setPriorrity(int newPriorrity):更改线程的优先级
yieId():暂停当前正在执行的线程对象,并执行其他线程。
public class Demo1 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0;i<3;i++){
System.out.println(Thread.currentThread().getName()+" i="+i);
}
}
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
Thread d1=new Thread(demo1);
d1.start();
//第二个线程用匿名类,匿名类就是不起名字,一般用于这个类我只用一次
new Thread(demo1).start();
new Thread(demo1,"线程3").start();//start是就绪
}
}
Thread-1 i=0
Thread-0 i=0
线程3 i=0
Thread-0 i=1
Thread-1 i=1
Thread-0 i=2
线程3 i=1
线程3 i=2
Thread-1 i=2
public class Demo2 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0;i<3;i++){
System.out.println(Thread.currentThread().getName()+" i="+i);
}
}
public static void main(String[] args) {
Demo2 demo2 = new Demo2();
Thread t1 = new Thread(demo2);
System.out.println("t1是否活动状态"+t1.isAlive());
t1.start();
System.out.println("t1是否活动状态"+t1.isAlive());
}
}
t1是否活动状态false
t1是否活动状态true
Thread-0 i=0
Thread-0 i=1
Thread-0 i=2
public void run() {
// TODO Auto-generated method stub
for(int i = 0;i<3;i++){
try {
Thread.sleep(1000);//一秒执行一次
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" i="+i);
}
}
//设置优先级,Windows下没有用
t1.setPriority(Thread.MAX_PRIORITY);//A最大
t2.setPriority(Thread.MIN_PRIORITY);//B最小
t3.setPriority(Thread.NORM_PRIORITY);//C默认
Java中每个对象都有一个内置锁,当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定=在对象上同步。
在多个线程同时访问互斥(可交换)数据时使用,应该同步以保护数据,确保两个线程不会同时修改更改它。比如我们只有四个包子,张三、李四、王五三个人,包子吃一次就没了,那么如果不用同步就会出错;用了同步就会对一个对象上锁,四个包子都得它才能吃。
非同步:
public class Demo1 implements Runnable{
private int baoZi = 4;
@Override
public void run() {
while(baoZi>0){
System.out.println(Thread.currentThread().getName()+"吃了第"+baoZi+"个包子");
baoZi--;
}
}
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
new Thread(demo1,"张三").start();
new Thread(demo1,"李四").start();
new Thread(demo1,"王五").start();
}
}
李四吃了第4个包子
王五吃了第4个包子
张三吃了第4个包子
王五吃了第2个包子
李四吃了第3个包子
张三吃了第1个包子
同步:两种方式
public class Demo2 {
private int baoZi = 4;
//同步方法
public synchronized void run() {
while(baoZi>0){
System.out.println(Thread.currentThread().getName()+"吃了第"+baoZi+"个包子");
baoZi--;
}
}
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
new Thread(demo1,"张三").start();
new Thread(demo1,"李四").start();
new Thread(demo1,"王五").start();
}
}
张三吃了第4个包子
张三吃了第3个包子
张三吃了第2个包子
张三吃了第1个包子
public class Demo3 {
private int baoZi = 4;
//2、同步块,范围更灵活
public void run() {
synchronized(this){
while(baoZi>0){
System.out.println(Thread.currentThread().getName()+"吃了第"+baoZi+"个包子");
baoZi--;
}
}
}
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
new Thread(demo1,"张三").start();
new Thread(demo1,"李四").start();
new Thread(demo1,"王五").start();
}
}
张三吃了第4个包子
张三吃了第3个包子
张三吃了第2个包子
张三吃了第1个包子