Java
2020-02-28 22:41:32 55 举报AI智能生成
java
java
模版推荐
作者其他创作
大纲/内容
Java语言基础
week1
Java 语言介绍
JAVA语言的诞生及发展<br>
JDK 1.0 (January 23, 1996)<br>JDK 1.1 (February 19, 1997)<br>J2SE 1.2 (December 8, 1998) <br>J2SE 1.3 (May 8, 2000)<br>J2SE 1.4 (February 6, 2002) <br>J2SE 5.0 (September 30, 2004) <br>Java SE 6 (December 11, 2006) <br>Java SE 7 (July 28, 2011) <br>Java SE 8 (March 18, 2014) <br>Java SE 9 (September 22, 2017 )<br>Java SE 10(March 22, 2018)<br>
JAVA语言的平台版本<br>
JAVASE
JAVASE(Java Platform Standard Edition)标准版,是为开发普通桌面和商务应用程序提供的解决方案。<br>
JAVAME
JAVAME(Java Platform To Micro Edition)小型版,是为开发电子消费产品和嵌入式设备提供的解决方案<br>
JAVAEE
JAVAEE(Java Platform To Enterprise Edition)企业版是为开发企业环境下的应用程序提供的一套解决方案<br>
JAVA语言的特点<br>
跨平台
面向对象
解释型<br>
健壮
动态
分布式
高效
多线程
结构中立(字节码) <br>
开源
问题
什么是跨平台性?<br>
通过Java语言编写的应用程序在不同的系统 平台上都可以运行。
跨平台的实现原理<br>
Java程序是在Java虚拟机上运行,而非直接运行于操作系统<br>
JDK与JRE<br>
JDK的下载和安装<br>
HelloWorld程序<br>
JAVA程序运行原理<br>
JDK 的介绍
Java 开发环境配置
基本语法
关键字
标识符
常量
进制转换
数据<br>类型
运算符
流程控制语句 <br>
数组
一维数组
二维数组
多维数组
方法
方法重载
面向对象
面向对象引入<br>
客观世界的构成
个体
联系
面向对象基本概念<br>
类
同种物体在属性和行为上的集合与抽象
对象
各个对象的属性取什么值,只有具体的对象能确定
面向对象基本语法<br>
成员变量
事物的属性
成员方法
事物的行为<br>
定义类<br>
分析类中的属性和行为,根据类的属性和行为来定义类。<br>
创建类的对象<br>
类名 对象名 = new 类名();
对象名.成员变量;<br>
对象名.成员方法
内存中的“对象”<br>
1个对象的内存图<br>
多个对象的内存图<br>
面向对象“特殊”语法<br>
局部变量和成员变量的比较
在类中定义的位置不同<br>
在内存中的位置不同<br>
生命周期不同<br>
初始化值不同<br>
基本数据类型和引用变量类型的比较
基本数据类型
引用变量类型
构造方法
作用
就是使得jvm在构造对象的时候,帮助我们进行成员变量的初始化。
格式
注意事项
this关键字
代表对象自身的引用
作用
解决成员变量的隐藏的问题<br>
访问对象的成员<br>
访问对象的构造方法<br>
static关键字
特点
随着类的加载而加载<br>
优先于对象而存在<br>
被类的所有成员所共享
可以通过类名访问<br>
注意事项
静态方法中是没有static关键字的<br>
静态方法只能访问静态的成员变量和静态的成员方法<br>
静态内容的存在于方法区中<br>
静态成员变量和普通成员变量的比较
所属不同<br>
静态变量属于类,所以也称为为类变量<br>
成员变量属于对象,所以也称为实例变量(对象变量)<br>
内存中的位置不同<br>
静态变量存储于方法区的静态区<br>
成员变量存储于堆内存<br>
内存出现时间不同<br>
静态变量随着类的加载而加载,随着类的消失而消失<br>
成员变量随着对象的创建而存在,随着对象的消失而消失<br>
调用不同<br>
静态变量可以通过类名调用,也可以通过对象调用<br>
成员变量只能通过对象名调用<br>
代码块<br>
引入
在Java中,使用{}括起来的代码被称为代码块,根据其位置和声明的不同,可以进行分类
分类
局部代码块
在方法中出现<br>
限定变量生命周期,及早释放,提高内存利用率
构造代码块 <br>
在类中方法外出现<br>
多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
如果有多个构造代码块,根据其书写的先后顺序来执行
静态代码块
在类中方法外出现,并加上static修饰<br>
用于给类进行初始化,在加载的时候就执行,并且值执行一次。
同步代码块
多线程部分再讲解
package关键字
引入
在Java源程序文件的第一行使用package声明可以使文件中定义的类成为指定包的成员<br>
语法
package 包名;
包名通常由多个名字字符串构成,中间用句点“.”分隔,每个名字表示的包称为其前面的名字表示的包的子包。<br>
通常以组织机构的域名反转形式作为其所有包的通用前缀,比如:com.somecompany.apps<br>
import关键字<br>
类的限定名
在类名前面加上类所属的包名,中间用句点“.”分隔,称为类的完全限定名(Full Qualified Name),简称类的限定名<br>
当在类体中使用了与当前类不同包的类名时,编译器编译时因为无法找到该类的定义而失败,有两个解决办法:<br>
使用不同包类的完全限定名<br>
使用import声明,为编译器提供该类的定义信息<br>
语法
import <类的完全限定名>;
注意事项<br>
import声明一般紧跟在package声明之后,必须在类声明之前
Java语言核心包java.lang包中的类将被隐式导入,可以直接使用其中的类<br>
import声明提供了一种包的智能导入方式import <包名>.*;<br> 包中的类将根据需要导入,避免使用多条import声明<br>
面向对象思想<br>
面向过程思想
所谓面向过程的编程思想,简单理解,程序是“动词”的集合,即程序功能是由一系列有序的动作来完成。
面向对象的思想
所谓面向对象的编程思想,简单理解,程序是由一系列的对象(消息)+消息组成,即程序是由一系列的对象和对象间的消息组成。
面向对象和面向过程的比较
结构化程序设计<br>
对应的典型的计算机语言, 例如: C<br>
面向操作的 <br>
函数(方法)是程序的基本单位<br>
面向对象程序设计<br>
对应的典型的计算机语言, 例如: Java, C++, C#<br>
面向对象(object)的<br>
类(class)是程序的基本单位<br>
类的初始化
变量作用域
类的访问控制权限
访问权限修饰符<br>
在Java语言中,一切事物(类所有成员)都具有(或显示定义或隐式定义的)访问权限,而这种语言层面的访问权限控制,是由访问权限修饰符实现。<br>
修饰类中成员(field & method)<br>
控制类中的成员,对其他类可见性(其他类是否可以直接使 <br> 用到)<br>
修饰类
通常用来限定,类库中的类(自定义数据类型),对于外部使 用者的可见性(是否能使用该类型)。
对类中成员的访问控制<br>
public
任意类均访问,实际就是没有限制访问权限<br>
protected<br>
同包中的其他类,和不同包的(可见)子类均可见
default(默认权限,隐式定义)<br>
同包中的其他类可见
private<br>
仅对同类中的其他成员可见<br>
注意点
能够修饰类的访问权限修饰符只有2种:<br>public 对其他任意类可见<br>default:对同包中的其他类可见<br>
为什么要使用访问控制修饰符?private<br>使用户不要触碰他们“不该”触碰的代码(private)<br>类库设计者可以安全的修改实现细节<br>
面向对象三大特性
封装
引入
封装是一种信息隐藏技术。<br>
是指将数据和基于数据的操作封装在一起<br>
数据被保护在内部<br>
系统的其他部分只有通过在数据外面 的被授权的操作才能够进行交互<br>
目的在于将类使用者class user和类设计者class creator分开。<br>
在面向对象的编程中,用类来封装相关的数据和方法,保证了数据的安全和系统的严密性。<br>
类<br>
成员变量(一定要考虑访问权限)<br>
构造方法<br>
无参构造方法<br>
带参构造方法<br>
成员方法<br>
getXxx()<br>
setXxx()<br>
注意点
给成员变量赋值的方式<br>
1.无参构造方法 + setXxx()<br>
2. 带参构造方法
继承
概述<br>
Java中的继承和我们现实生活中的“继承”的含义基本类似,但是含义更广。<br>
简单来说都可以表示“不劳而获”<br>
类型之间“is a”的关系<br>
被继承的类称之为父类(基类或超类),继承其他类的类称之为子类(派生类)<br>
子类可以通过继承机制,不写任何额外代码就可以拥有父类的“所有”成员。<br>
基本含义
a. 子类通过继承父类,子类就拥有了父类中定义的所有成员
b. 一旦子类继承了父类,子类 和 父类这两种类型有了关系
c.子类可以被当做父类类型来使用。<br>父类类型 引用 = new 子类类型();
语法<br>
class 子类名 extends 父类名 {}
优点
代码复用(方法,类)
提高了代码的可维护性(这是一把双刃剑)<br>
弱化Java中的类型约束(多态的前提)<br>
A类型的 引用变量 = new A();<br> 学习继承之后(B类 继承自 A类);<br> A类型的 引用变量 = new A();<br> A类型的 引用变量 = new B(); 因为 类B继承自类A。
缺点
父类的修改可能会出现在所有子类中(我们无法选择这些修改可以反应在,哪些子类中,不可以反应在哪些子类中)<br>
注意点
在Java中只能实现单重继承,简单来说Java的extends关键字后只能跟一个类名<br>
但是因为可以有继承层次,并不意味着一个java类只能继承另外一个类的成员
子类能够继承父类的私有成员,但是不能直接访问,可以定义方法进行间接访问<br>
子类不能继承父类的构造方法<br>
内存映像
定义子类对象的过程
1.定义一个子类对象
2.加载父类
3.加载子类
4.在内存开辟父类变量的存储空间
5.在内存中开辟子类变量的存储空间
子类对象的两部分值
父类中定义的成员变量的值
子类中定义的成员变量的值
子类对象的初始化问题
初始化过程
1.先初始化父类成员变量的值
2.再初始化子类成员变量的值
理解的两个角度
a. 子类继承父类,父在先,自在后,父类成员变量先初始化,然后才是子类自己定义的成员变量值的初始化。
b. 初始化子类成员的时候,子类成员变量的初值,和父类成员变量的值有关系
如何实现,在子类对象中,先初始化父类成员变量的值,再初始化子类成员变量的值?<br>----保证父类的的构造方法先执行,子类的构造方法后执行。
隐式初始化
a.当父类提供了默认的构造函数,且子类的构造函数中没有显示调用父类的其他构造函数
b.则在执行子类构造函数之前(jvm)会自动执行父类的默认构造函数
显式初始化
我们自己通过在子类构造方法中,先调用父类构造方法,再执行子类构造方法。
如何在子类构造方法中显式的调用父类的构造方法?通过super关键字
super关键字
super 代表父类对象的引用
1. super.成员变量 访问父类对象的成员变量的值
2. super.成员方法 访问父类中定义的成员方法
3. super(..) 调用父类的构造方法
域的隐藏
a. 在子类中是否可以定义和父类同名的成员变量?
可以
b. 如果可以,那么在子类中访问这个同名变量,究竟访问到的是父类对象中的值,<br>还是子类对象中的值?如果在父类中访问呢?
1. 在子类类体中,同过变量名,访问到的是,子类中定义同名成员变量的值
2. 在父类类体中,通过变量名,访问到的是,父类中定义的同名成员变量的值
c. 是否可以在子类对象中,同时访问到子类对象和父类对象中的同名成员变量的值?
1. 对于子类中定义的成员变量的值,直接通过同名变量的变量名可以直接访问到
2. 在子类类体中,利用super关键,指明我们要访问的同名成员变量,父类中定义的成员变量的值
方法的覆盖或重写(override)
引入
子类中定义了和父类完全相同的方法,子类覆盖了父类中定义的方法
问题
1.子类中能否定义和父类一模一样的方法?
可以
2.如果可以,那么在子类对象中访问这个一模一样的方法,<br> 究竟访问到的是父类对象中的方法,还是子类对象中的方法?如果在父类中访问呢?
a. 在子类类体中直接通过方法名,访问到的一模一样的方法,是子类自己定义的一模一样的方法
b. 在父类类体中,直接通过方法名,方问这个一模一样的方法, 仍然是子类中定义的那个一模一样的方法
说明
因为一旦在子类类体中,定义了和父类类体中一模一样的方法,在父类类体中,就无法访问到<br>父类中自己定义的那个成员方法了,就好像,父类的方法被子类中定义的那个一抹一样的方法给覆盖掉了
3.是否可以在子类对象中,同时访问到子类对象和父类对象中的同名成员方法?
可以,通过super关键字
使用场景
修改父类方法实现<br>1.有时候我们想要复用别人的代码,通过继承来复用<br> 2. 继承的是其他类所有的成员方法,但是有些方法可能对于我们来说,并不适用<br>3. 通过方法覆盖(重写),修改父类中的方法实现<br>
注意事项
1.父类中私有方法不能被重写(覆盖)
2.子类重写父类方法时,子类方法访问权限不能更低
3.静态方法不能被重写(覆盖)
@Override注解检测子类方法是否覆盖父类方法
在子类中,覆盖父类方法的条件
1.对于方法的访问权限,子类中覆盖父类的方法,它的方法不能小于父类方法的访问权限。
2.子类方法的方法签名,必须和父类相同。 <br>
3.对于返回值而言
a.子类方法和父类方法声明的返回值可以相同。
b.子类方法和父类方法声明的返回值可以不相同。
但是子类方法的返回值类型必须是父类方法的返回值类型的子类。<br>因为,子类对象可以被父类对象接收。
补充
测试跨包子类的访问权限<br>类体中可以直接访问父类中定义的被protected访问权限修饰符修饰的成员<br>通过父类对象不可以直接访问到该成员,<br>通过子类对象可以直接访问到该成员。
final关键字
概念
final是最终的意思,可以修饰类,变量,成员方法。
a.修饰类,类不能被继承
b.修饰变量,变量就变成了常量,只能被赋值一次
常量有字面值常量、自定义常量
final修饰变量时分为2种情况:
1.修饰成员变量<br>
可以在定义时初始化
可以选择在构造代码块中进行初始化
可以选择在构造方法中进行初始化
(在对象创建真正完毕之前,也即定义后、使用前。)
2.修饰局部变量
3.修饰方法,方法不能被重写(override)
多态
概念
某一个事物,在不同时刻(或条件下)表现出来的不同状态。
条件
1.继承(父类、子类)<br>
2.发生多态的行为(方法),子类中子类必须覆盖父类中的该方法。
3.父类引用指向子类实例
父类 引用 = new 子类()
两种多态
a.编译时多态
方法重载
编译时根据方法签名就能确定调用那个方法。
b.运行时多态
成员访问特点<br>
成员变量<br>
编译看左边,运行看左边
1. 成员变量:通过父类引用访问子类对象的时候,如果子类中定义了和父类命名的成员变量,访问到的是父类中同名成员变量的值。<br>
成员方法
编译看左边,运行看右边
2. 成员方法:父类引用,指向的具体是哪种子类对象,通过引用变量访问到的方法,就是相应子类类型中定义的方法。
编译看左边
a.多态条件下 父类引用 = new 子类类型();<br>
b.编译看左边,通过父类引用可以访问到的成员范围,是根据引用类型来确定。<br>(也就是说,引用变量.成员,只能访问父类的成员)
好处
提高了程序的维护性(由继承保证)<br>
提高了程序的扩展性(由多态保证)<br>
弊端
不能访问子类特有功能<br>
多态中的转型
向上转型
从子到父,即父类引用指向子类对象<br>
注意:向上转型,是Java语言天生就允许的<br>
向下转型
从父到子,即父类引用转为子类对象的引用<br>
向下转型是不安全的,因此Java语言默认不允许向下转型
如何能做到安全的向下转型呢? instanceof<br> 对象名 instanceof 类名<br>
week2
抽象类
定义
包含有抽象方法的类或被abstract修饰的类
abstract关键字
抽象类和抽象方法必须用abstract关键字修饰 abstract class 类名 {}<br>
注意点
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类<br>
抽象类不能直接实例化<br>
抽象类的子类可以是抽象类,也可以是具体类<br>
抽象类的成员特点
构造方法
同普通类
疑问
不能实例化,为啥有构造方法?
成员变量
同普通类
成员方法
可以是抽象方法,也可以是非抽象方法
问题
一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?<br>//可以,不想让别人将这个类直接实例化。<br>
abstract不能和哪些关键字共存<br>private<br>final<br>static<br>
接口
引入
Java中有专门用来表示一组特殊功能(仅仅只是声明,没有具体实现)的工具——接口
子主题
子主题
子主题
内部类
引入
在Java语言中类可以嵌套定义。<br>
内部类:定义在其他类内部的类就称为内部类<br>
访问特点
内部类可以直接访问外部类的成员,包括私有。
外部类要访问内部类的成员,必须创建对象。
按照内部类在类中定义的位置不同,可以分为如下两种格式:<br>
成员位置(成员内部类)<br>
成员位置内部类:类中方法体之外
从外部类的角度来理解,因为内部类定义在外部类的成员位置,如果说我们把内部类看做是一个整体,将内部类看做是外部类的一个“成员”
内部类的访问<br>
外部类的外部
外部类名.内部类名 对象名 = 外部类对象.内部类对象;<br>
分两步完成
第一步(创建外部类对象)<br> Outer outer = new Outer();
第二步(创建内部类对象)<br>Outer.MemberInner memberInner = outer.new MemberInner();<br>
一步完成
一步创建成员位置内部类对象<br>Outer.MemberInner inner = new Outer().new MemberInner();
在外部类的外部,创建静态成员位置内部类对象<br> Outer.StaticInner staticInner = new Outer.StaticInner();
外部类
外部类要访问内部类的成员,必须创建对象。<br>a.创建对象<br>b.访问内部类的成员方法<br>c.通过内部类对象,访问其成员变量
成员内部的常见修饰符<br>
private
保证成员位置内部类只对其外部类可见
static<br>
静态内部类的访问特征
静态内部类本身,就是一个静态上下文
在成员位置静态内部类中,无法直接访问外部类的非静态成员
局部位置(局部内部类)<br>
注意局部内部类的定义位置:方法体内<br>
局部内部类的使用<br>
可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
一个特征
可以访问到,方法体内部定义的局部变量
注意事项<br>
被局部内部类访问的局部变量,被final修饰或 effectively final<br> effectively final 就是一个常量,在初次赋值之后,其值再也没有变过<br> 为什么? 生命周期<br>a. 局部变量的生命周期,随着方法的执行完毕,而被销毁<br>b. 当方法运行完毕之后,如果说内部对象还没有变成垃圾,<br> 并且可以通过内部类对象,访问到内部类对象的成员方法,<br> 此时局部内部类对象就有可能访问,局部变量,<br> 但此时,局部变量已经随着外部类方法的执行完毕而被销毁了<br> 已经访问不到了。<br>
补充
有关this
class Outer1 {<br> public int num = 10;<br> class Inner {<br> public int num = 20;<br> public void show() {<br> int num = 30;<br> // 类名.this 主要出现在嵌套的类定义中<br> // 类名.this和static没有任何关系<br> // 通过类名.this,来表明this那个类的当前对象<br> // 此时的类名,只是用用来指明嵌套的层级<br> System.out.println(Outer1.this.num);<br> System.out.println(Inner.this.num); //这个this指的当前是内部类对象num成员变量<br> System.out.println(num);<br> }<br> }<br>}<br>//在控制台分别输出10,20,30
匿名内部类对象<br>
引入
回顾一下,不管是成员或局部位置内部类,我们要使用内部类都分成了2步:<br>a.定义内部类<br>b.创建内部类对象<br>通过定义匿名内部类对象,我们可以将上面的2步变为1步。<br>
匿名内部类的前提
存在一个类或者接口,这里的类可以是具体类也可以是抽象类。<br>
匿名内部类对象<br>
new 类名或者接口名() {重写方法;}
{} 中实际上是一个类定义,只不过这个类我们并没专门给这个类起名字<br>但是,这个类也应该是有类型的,它所属的类型,就是它的父类类型<br>匿名内部类,存在的前提是存在一个类或者接口
本质
是一个继承了类或者实现了接口的子类匿名对象
注意点
1. 直接用匿名内部类对象,可以访问到匿名子类中,自己定义的子类成员(再匿名类后面+.成员),包括成员方法和成员变量。成员变量值可以用一个新的变量来接收。
2. 匿名子类中,可以再定义新的方法
3. 可以用父类引用指向子类的匿名内部类对象(方便复用)
4. 可以直接创建一个针对接口的匿名内部类对象<br> 可以直接创建一个抽象类的子类对象<br> 也可以直接创建一个已经存在的普通类子类对象
匿名子类中可以添加或改写(重写)成员变量和成员方法
因为本质上匿名内部类是一个继承了类或实现了接口的子类匿名对象
5. 匿名对象,只能在new对象的时候,访问这个对象一次
就是只使用接口或者抽象类子类对象一次(通过匿名内部类对象合二为一)
6. 形式参数是接口类型方法,可以在调用该方法啊的时候,把实现了接口的匿名内部类作为形式参数。这样可以使用一次该接口的实现。
Java常见类
Object类
定义
Object类是类层次结构的根类,所有类都直接或者间接的继承自该类<br>
构造方法
public Object();<br>
Object的成员方法<br>
public int hashCode()<br>
public final Class getClass()
public String toString()
public boolean equals(Object obj)
protected void finalize()
protected Object clone()
String类
引入
字符串是由多个字符组成的一串数据(字符序列)<br>
字符串可以看成是字符数组
一个String类对象,代表一个字符串
注意点
Java语言中,字符串的特征:字符串是常量,它的值在创建之后不能更改
String类,自己覆盖了Object类中的equals方法,比较的是字符串内容
//堆中的两个不同String对象<br> //String s1 = new String("hello");<br> //String s2 = new String("hello");<br> //System.out.println(s1==s2); // false<br> //System.out.println(s1.equals(s2)); // true
//s3, 指向堆中的字符串对象<br> //s4, 指向方法区的常量池中的 "hello"<br> //String s3 = new String("hello");<br> //String s4 = "hello";<br> //System.out.println(s3 == s4); // false<br> //System.out.println(s3.equals(s4)); //true
//两个引用都指向方发区,常量池中的"hello"<br> //String s5 = "hello";<br> //String s6 = "hello";<br> //System.out.println(s5==s6); //true<br> //System.out.println(s5.equals(s6)); //true
问题
字符串是常量,它的值在创建之后不能更改<br>String s = “hello”; s += “world”; 问s的结果是多少?<br>
String s = new String(“hello”)和String s = “hello”;的区别?<br>字符串比较之看程序写结果<br>字符串拼接之看程序写结果<br>
String构造方法
public String()<br>
创建一个空字符串
public String(byte[] bytes)
将一个字节数组代表的数值序列(ascII码表),当做字符串创建
public String(byte[] bytes,int offset,int length)
利用字节数组的一部分,来创建字符序列对象的字符串对象
范围:[offset, offset + length)
offset: 从字节数组的那个位置开始
length: 从offset开始,要使用多少个字节值,来创建字符序列
public String(char[] value) <br>
创建一个字符数组多代表的字符序列对应的字符串对象
public String(char[] value,int offset,int count)
利用字符数组的一部分,来创建字符序列对象的字符串对象
public String(String original)
String类的的判断功能
boolean equals(Object obj)<br>boolean equalsIgnoreCase(String str)<br>boolean contains(String str)<br>boolean startsWith(String str)<br>boolean endsWith(String str)<br>boolean isEmpty()<br>
String类的的获取功能
int length()<br>
获取字符串的长度
char charAt(int index)
获取字符串中指定位置的字符
int indexOf(int ch)
在字符串序列中查找指定字符在序列中首次出现的位置
int indexOf(String str)
在字符串序列中查找指定字符串在序列中首次出现的位置
int indexOf(int ch,int fromIndex)
int indexOf(String str,int fromIndex)
String substring(int start)
String substring(int start,int end)
String类的的转换功能
byte[] getBytes()<br>char[] toCharArray()<br>static String valueOf(char[] chs)<br>static String valueOf(int i)<br>String toLowerCase()<br>String toUpperCase()<br>String concat(String str)<br>
String类的替换功能<br>
String replace(char old,char new) <br>
String replace(String old,String new)
String类去除空字符串
String trim()
String类的比较功能
int compareTo(String str)<br>
int compareToIgnoreCase(String str)
StringBuffer<br>
Date
DateFormat
Math
异常
异常概述<br>
什么是异常?<br>
简单来说异常就是用来表示Java程序运行过程中的错误(信息)<br>
Java异常机制的由来
C语言时代的错误处理<br>
Java的基本理念<br>
错误恢复机制<br>
让我们的程序,在运行过程,具有"自修复能力"的一种错误报告模型
Java异常机制的实质
就是提供了一致性的错误报告模型,使得类的构建者和使用者之间可以进行可靠的沟通<br>
常见异常
数组越界,除0异常
异常的分类
根据java程序在运行过程中,根据程序运行时错误的严重程度,异常可分为:<br>
Exception:在程序中可能能够处理的错误<br>
Error:程序层面无法处理的错误<br>
对于Exception,根据错误处理方式的不同<br>
编译时异常(Checkable Exception)<br>
指的是Exception及其直接子类(除了Runtimexception)
可预见的,语法层面强制在代码编写时处理
运行时异常(Runtime Exception)<br>
指的是RuntimeException及其直接子类
不可预见的,不要求在编写代码时必须处理<br>
最早的异常处理
口头约定
假设有这样一个方法,实现了一定的功能,可以让别人来调用。<br> 但是,这个方法在运行的时候,可能会出错,约定返回-1,表示我这个方法运行的时候,出了问题,结果是错的。<br> 在这个方法中实现了一些功能,一旦出了运行时错误 首先收集错误信息,然后向上(方法调用者)报告。
JVM的默认异常处理
当我们的程序在正常执行的过程中,发生了“错误”,默认情况下,JVM如何处理呢?<br>
程序停止运行<br>
控制台窗口,输出了错误信息,以及错误的调用相关信息<br>
获取异常信息
我们通常所使用的,获取异常信息的方法,都是定义在Throwable类中的
getMessage()<br>
获取异常信息,返回字符串。
toString()<br>
获取异常类名和异常信息,返回字符串。
printStackTrace()<br>
获取异常类名和异常信息,以及异常出现在程序中的位置,并打印到控制台<br>
printStackTrace(PrintStream s)<br>
该方法将异常内容保存在日志文件中,以便查阅。
Java的异常捕获机制
加入异常处理后的代码执行逻辑<br>
try {<br> //部分可能发生异常的,正常的代码逻辑<br>} catch(异常类型 e) {<br> //每一个catch分支对应一个异常处理器<br> //在catch分支中处理具体类型的代码异常<br>}<br>另外的代码逻辑<br>……<br>
多分支的异常匹配<br>
try {<br> //部分可能发生异常的,正常的代码逻辑<br>} catch (异常1类型 e) {<br> //每一个catch分支对应一个异常处理器<br> //在catch分支中处理具体类型的代码异常<br>} catch (异常2类型 e) {<br>}<br>……<br>
运行时异常 VS 编译时异常<br>
所有的RuntimeException类及其子类的实例被称为运行时异常,其他的异常就是编译时异常
运行时异常<br>
无需显示处理,也可以和编译时异常一样处理
编译时异常<br>
Java程序必须显示处理,否则程序就会发生错误无法通过编译<br>
抛出异常
throws<br>
在方法定义时使用<br>
声明该方法可能抛出的异常<br>
对于编译时异常,可以在语法层面个强制方法调用者处理该异常<br>
基本语法
修饰符 返回值(形参列表) throws 异常列表 {}<br>
注意事项
异常列表之间用逗号分割,列表中出现的异常不要出现包含关系<br>
方法覆盖时的子类异常列表必须与父类兼容<br>
throw<br>
在方法体中使用<br>
主动在程序中抛出异常<br>
每次只能抛出确定的某个异常对象<br>
基本语法
throw 异常对象<br>
注意事项
若要抛出编译时异常,则必须和throws配合起来使用<br>
throws VS throw<br>
throws<br>
1.用在方法声明后面,跟的是异常类名<br>2.可以跟多个异常类名,用逗号隔开<br>3.表示抛出异常,由该方法的调用者来处理<br>4.throws表示出现异常的一种可能性,并不一定会发生这些异常<br>
throw<br>
1.用在方法体内,跟的是异常对象名<br>2.只能抛出一个异常对象名<br>3.表示抛出异常,由方法体内的语句处理<br>4.throw则是抛出了异常,执行throw则一定抛出了某种异常<br>
总结
异常的处理策略主要有两种
捕获并处理<br>
向上抛出<br>
如何选择处理策略呢?<br>
原则
如果该功能内部可以将问题处理用try
如果处理不了,交由调用者处理用throws
异常一旦被捕获,并且没有再次被抛出,那么上层是感知不到该异常的!!!!<br>
finally
特点
被finally控制的语句体一定会执行。<br>特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))<br>
对于try-catch-finally代码块而言,finally代码块中的代码,不管是否发生异常,finally代码块中的代码都会被执行。
即使在finally代码块之前有return语句,finally块中的代码仍会执行
作用
用于释放资源,在IO流操作和数据库操作中会见到<br>
在开发中,我们希望,不管程序,正常执行,非正常终止,都希望在某些代码运行完之后,一定能及时释放系统资源
相关的面试题
final,finally和finalize的区别<br>
a. final 最终的意思,修饰类,变量(成员变量和局部变量),成员方法<br>
b. finally 代码块
c. finalize() Object类中的一个方法
如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问是在return前还是return后。<br>
自定义异常
继承自Exception<br>
编译时异常
继承自RuntimeException<br>
运行时异常
自定义异常,存在的意义,不在客制化的异常描述,而在于异常的处理
一旦自定义异常之后,在处理异常的时候,就可以有一个专门针对,你自己定义的这种异常情况的分支
File类<br>
概述
文件和目录路径名的抽象表示形式<br>
一个File类对象,它描述的就是一个,路径名字符串,所表示一个文件或目录
a. 绝对路径:绝对路径名是完整的路径名,不需要任何其他信息就可以定位它所表示的文件 f:\devlopment\a.txt<br> b. 相对路径: 相对路径名必须使用取自其他路径名的信息进行解释 (相对父路径) develop\b.txt
相对路径和绝对路径在不同操作系统中的表示
a. 对于 UNIX 平台,绝对路径名的前缀始终是 "/"。<br>相对路径名没有前缀。表示根目录的绝对路径名的前缀为 "/" 且名称序列为空。<br> 绝对路径: /dir/file.txt /表示根目录<br>相对路径: dir/a.exe
b. windows: 绝对路径: 盘符:\<br> f:\devlopment\a.txt<br> 相对路径:没有盘符:\前缀的路径,都是相对路径
注意有双引号是双反斜杠
默认情况下,java.io 包中的类总是根据当前用户目录来解析相对路径名。此目录由系统属性 user.dir 指定,通常是 Java 虚拟机的调用目录<br><br> 相对路径: development\b.txt<br><br> 当前用户路径 + develop\b.txt <br>
获取 系统属性 user.dir属性名
System.out.println(System.getProperty("user.dir"));
构造方法
File (String pathname)<br>
String path = "d:\\dir\\a.txt";<br>File file = new File(path);
对于File类对象而言,不一定File对象表示文件或者目录就一定是在操作系统中存在的文件或目录
即使文件不是真的存在,运行也不会报错
File类对象,表示的是抽象路径字符串,所表示的那个文件
File (String parent, Sting child)
file = new File("e:\\dir\\first", "a.txt");// e:\dir\first\a.txt
File (File parent, String child)
File parentDir = new File("e:\\dir\\first");<br>file = new File(parentDir, "a.txt");// e:\dir\first\a.txt
file的成员变量
public static final String pathSeparator<br><br> * 与系统有关的路径分隔符,为了方便,它被表示为一个字符串。此字符串只包含一个字符,即 pathSeparatorChar。
public static final char pathSeparatorChar<br><br> * 与系统有关的路径分隔符。此字段被初始为包含系统属性 path.separator 值的第一个字符。<br><br> * 此字符用于分隔以路径列表 形式给定的文件序列中的文件名。
在 UNIX 系统上,此字段为 ':';<br> 在 Microsoft Windows 系统上,它为 ';'。
* windows: 一个字符串中包含了多个路径路径与路径之间 e:\a.txt;d:|a.txt<br><br> * unix: /zs/a.txt:/zs/b.txt
* public static final String separator与系统有关的默认名称分隔符,<br><br> * 为了方便,它被表示为一个字符串。此字符串只包含一个字符,即 separatorChar。
* public static final String separator与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。<br><br> * 此字符串只包含一个字符,即 separatorChar。
* public static final char separatorChar与系统有关的默认名称分隔符。<br><br> * 此字段被初始化为包含系统属性 file.separator 值的第一个字符。<br><br> * 在 UNIX 系统上,此字段的值为 '/';<br><br> * 在 Microsoft Windows 系统上,它为 '\\'。 dir\a\b.txt
成员方法
创建功能<br>
public boolean createNewFile() <br>
在操作系统上物理创建文件<br>
File file = new File("e:\\", "a.txt");//创建一个File类对象 e:\a.txt<br> boolean newFile = file.createNewFile();//物理创建<br>System.out.println(newFile);
public boolean mkdir()<br>
当目标目录的父目录不存在的时候,mkdir()会创建布标目录失败
创建目录 e:\\aaa<br> file = new File("e:\\aaa");<br>boolean mkdir = file.mkdir();<br>System.out.println(mkdir);
public boolean mkdirs()<br>
当目标目录的父目录不存在的时候,mkdirs(),会连同目标目录和不存在的目标目录的父目录,一起创建出来
file = new File("e:\\aaa", "bbb");<br> boolean mkdirs = file.mkdirs();<br> System.out.println(mkdirs);
删除功能<br>
public boolean delete()<br>
删除文件或目录, 如果此路径名表示一个目录,则该目录必须为空才能删除
//删除文件<br> File file = new File("e:\\a.txt");<br> boolean delete = file.delete();<br>System.out.println(delete);
//删除目录<br> File dir = new File("e:\\aaa");<br>System.out.println(dir.delete());<br>//e:\\aaa目录中有一个bbb目录,故返回false,删除失败
重命名功能<br>
public boolean renameTo(File dest)<br>
a. 如果是目标文件对象和当前文件对象,在同一目录下,实现的效果就是重命名<br><br> b. 如果是目标文件对象和当前文件对象,不在同一目录下,除了重命名,文件移动
//重命名: e:\a.txt -> e:\d.txt<br><br> //File targetFile1 = new File("e:\\d.txt");<br><br> File targetFile2 = new File("d:\\d.txt");<br><br> boolean result = file.renameTo(targetFile2);<br><br> System.out.println(result);
判断功能<br>
public boolean isFile()<br>
File file = new File("e:\\a.txt");<br>//System.out.println(file.isFile()); //true<br>
file = new File("e:\\a");<br> //System.out.println(file.isFile());// false
public boolean isDirectory()
File file = new File("e:\\a.txt");<br> //System.out.println(file.isDirectory()); //false<br>
file = new File("e:\\a");<br>//System.out.println(file.isDirectory()); // true<br>
public boolean exists()
物理判断File对象表示的文件或目录是否真的存在
file = new File("e:\\zs\\a.txt");<br> System.out.println(file.exists());//true or false
public boolean canRead()
public boolean canWrite()
public boolean isHidden()
基本获取功能<br>
public File getAbsoluteFile()<br>public String getPath()<br>public String getName()<br>public long length()<br>public long lastModified()<br>
File file = new File("a.txt");<br>System.out.println(file.getAbsolutePath()); //E:\wangdao\20th\exception&file\a.txt<br>System.out.println(System.getProperty("user.dir"));//E:\wangdao\20th\exception&file<br> System.out.println(file.getPath()); //返回的就是创建File对象时,所使用的字符串路径//a.txt<br> System.out.println(file.getName()); //文件名或者目录名//a.txt
File file = new File("e:\\zs\\a.txt");<br>System.out.println(file.getAbsolutePath()); //e:\zs\a.txt<br>System.out.println(file.getPath()); //e:\zs\a.txt<br>System.out.println(file.getName()); //a.txt
高级获取功能<br>
public String[] list()<br>
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。<br> 如果此抽象路径名不表示一个目录,那么此方法将返回 null
//一个File类对象可以表示一个目录<br> File dir = new File("e:\\a");<br> String[] list = dir.list();<br> System.out.println(Arrays.toString(list)); //[b, zs.txt]
public File[] listFiles()
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的目录和文件<br> 如果此抽象路径名不表示一个目录,那么此方法将返回 null
File[] files1 = dir.listFiles();<br> System.out.println(Arrays.toString(files1));//[e:\a\b, e:\a\zs.txt]
自定义获取功能<br>
File[] listFiles(FileFilter filter)<br>String[] list(FilenameFilter filter)<br>File[] listFiles(FilenameFilter filter)<br>
自定义获取: 自定义在哪里呢? 就是我们可以自己指定,所要查找的文件,需要满足的过滤条件<br><br> * list或listFiles方法的参数,它们都是用来表名,你定义的过滤条件的
两种过滤器接口<br>
FileFilter<br>
public interface FileFilter {boolean accept(File pathname);}<br>
FilenameFilter<br>
public interface FilenameFilter {boolean accept(File dir, String name);}<br>
public interface FilenameFilter {<br><br> boolean accept(File dir, String name);<br><br>}<br><br> File[] listFiles(FilenameFilter filter)<br><br><br><br> java io包,Filefilter {<br><br> 返回值:true 说明待判断文件(accept方法的形式参数)满足过滤条件<br><br> false 说明待判断文件(accept方法的形式参数)不满足过滤条件<br><br> boolean accept(File pathname)<br><br> }<br><br> 具体的过滤条件? Filefilter子类对象中,我们自己来定义具体的过滤条件
A callback is a function that is passed as an argument to another function<br><br> and is executed after its parent function has completed. <br>
多线程
多线程<br>
为什么引入多线程
多线程的实现方式一 <br>
Java程序的运行
多线程相关API
线程的生命周期
多线程的实现方式二 <br>
线程安全问题
线程安全问题的解决
线程锁<br>
Lock锁机制
synchronized关键字,虽然可以理解加锁,解锁的原理,但是却看不到具体的过程。<br>实现同步代码块,除了使用synchronized之外,其实JDK1.5之后,提供了另外的方式Lock锁机制<br>
Lock:表示锁的接口,其实现机制与synchronized不同<br>lock()<br>unlock()<br>
常用子类:ReentrantLock<br>
死锁问题
同步另一个弊端:如果出现了嵌套锁,容易产生死锁<br>
死锁问题:<br> 死锁是指两个以上的线程在执行过程中,因为争夺资源而产生的一种相互等待的现象<br>
生产者消费者模型
线程间通信(wait-notify)
线程间通信,Java中主要通过Object中的方法来实现:<br>
wait()//克制自己 <br>
克制自己,导致当前线程等待,处于阻塞状态。
其他线程,调用此对象的notify()方法或notifyAll()方法的时候,才会醒过来。因为m对象的wait()方法而处于阻塞状态的线程A,若要唤醒该线程A,必须在其他线程中,同一个对象m上调用其notify(),或notifyAll()方法,才能唤醒因为m对象的wait()方法处于阻塞状态的线程A。
wait()方法不是随便能调用的,当前线程必须拥有对象监视器(对象监视器,就可以理解为对象中的锁标志位,就是对该对象加锁)。对象m.wait(),要在对象上成功调用wait()方法,必须保证,当前线程首先得持有锁对象。 synchronized(m){m.wait();}
当我们成功调用wait方法之后,除了导致当前线程等待之外,还有其他功能:该对象发布对此监视器的所有权并等待。调用wait方法的线程,会导致当前线程放弃持有锁对象。
notify()//通知别人
唤醒在此对象监视器上等待的单个线程,如果所有线程都在此对象上等待,则会选择唤醒其中的一个线程,选择是任意性的
notifyAll()//通知别人
唤醒那些因为对象m.wait(),而处于阻塞状态的线程
完整的多线程状态转化图
线程池
定时任务
week3
Java IO 流,概述、分类、字节流基类,常见读写方<br><br>式,缓冲流,字符流基类,编码表,字符缓冲流;打印<br><br>流,标准输入输出流,序列化流等 Java 网络编程、网<br><br>络编程概述、网络编程三要素 、UDP 编程 、TCP 编程<br><br>等 l 类加载器,反射,通过反射获取构造方法,成员变量,<br><br>及私有方法调用<br><br>l JAVA 注解的使用<br><br>l Java 虚拟机架构介绍,java 虚拟机内存管理,JVM GC<br><br>介绍,垃圾回收原理,常见垃圾回收算法,OOM 及<br><br>Memory leak 问题分析。
I/O
I/O的概念<br>
I/O:Input/Output <br>
为啥需要I/O?<br>
在操作系统中,一切数据都以文件的形式存储。<br>需要长久保存的文件数据,存储在外部设备。<br>同时,内存的大小有限,因此常常需要在内存和外设之间交换数据,即I/O
而Java语言主要通过InputStream和OutputStream,完成I/O的功能,从而实现和外设的数据交互。
Java I/O流
I/O流:IO流用来处理JVM和外部设备之间的数据传输<br>Java通过流(Stream)的方式,操作数据的传输过程。<br>
I/O流的分类
按数据流向
输入流 读入数据
输出流 写出数据
按照数据类型<br>
字节流:数据是一连串01二进制数据
字符流:数据是字符序列
如何区分使用字节流还是字符流?
文本数据用字符流,如果不确定内容,就用字节流。
I/O流常用基类
字节流的抽象基类:<br>
InputStream 字节输入流
OutputStream 字节输出流
字符流的抽象基类<br>
Reader 字符输入流
Writer 字符输出流 <br>
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。<br>如:InputStream的子类FileInputStream。<br>如:Reader的子类FileReader
字节流写数据 <br>
通过OutputStream对象,完成向文本文件中输出” hello world” <br>但是注意到,OutputStream是抽象类,如果要使用OutputStream对象,只能使用其子类对象,完成写入功能。<br> 这里还需要注意的是,虽然写入的数据是文本数据,但是还没学字符流,所以先使用字节流。<br>
FileOutputStream的构造方法
FileOutputStream(File file)
FileOutputStream(String name)
字节流写数据的方式<br>
public void write(int b)<br>
将指定的字节写入此输出流。write 的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。
public void write(byte[] b)
将 b.length 个字节从指定的 byte 数组写入此输出流
public void write(byte[] b,int off,int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流
字节流写数据常见问题
创建字节输出流到底做了哪些事情?<br>
1. FileoutputStream会现在操作系统中,找目标文件<br><br> a. 如果说目标文件不存在,FileoutputStream创建这个文件<br><br> b. 如果该文件存在,则不再重新创建<br><br> 2. 在内存中,创建FileOutputStream对象,并建立数据传输的通道
数据写成功后,为什么要close()? <br>
关闭此输出流并释放与此流有关的所有系统资源。
如何实现数据的换行?
不同的操作系统,换行符不一样<br><br> windows操作系统: '\r''\n'<br><br> linux,Mac OS: '\n'<br><br> 对于一些高级记事本,都可以识别
如何实现数据的追加写入? <br>
a. 如果在创建FileOutputStream对象的时候,目标文件已经存在<br><br> FileOutputStream对象,它会自动清空,已经存在的文件内容<br><br> 从文件的最开始出,开始写入<br><br><br><br> FileOutputStream(File file, boolean append)<br><br> 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。如果第二个参数为 true,<br><br> 则将字节写入文件末尾处,而不是写入文件开始处<br><br><br><br><br><br> FileOutputStream(String name, boolean append)<br><br> 创建一个向具有指定 name 的文件中写入数据的输出文件流。
子主题
D盘
文件夹test2
文件夹test21
文件夹test211
文件夹2111
test211.java
文件夹test22
java.jpg
test1.java
test2.java
test3.txt
G盘
文件夹test2
文件夹test21
文件夹test211
文件夹2111
test211.java
文件夹test22
test1.java
test2.java
子主题
给I/0流操作加上异常处理
字节流读数据
FileInputStream的构造方法<br>
FileInputStream(File file)<br>
FileInputStream(String name)<br>
FileInputStream的成员方法<br>
public int read()//一次读取一个字节<br>
public int read(byte[] b)//一次读取一个字节数组<br>
缓冲流
BufferedOutputStream//字节缓冲输出流<br>
BufferedInputStream//字节缓冲输入流<br>
Java语言进阶
week4
l JAVA 集合的使用,Collection<br><br>l ArrayList l HashMap l Set<br><br>l JDK 集合代码如 HashMap 解析
week5
l Java 数据结构 l 线性表/ l 链表/ l 二叉树<br><br>l 常见排序算排序 l 红黑树/B 树/B+树
子主题
子主题
Ctrl + Alt + T快捷键
Shift + F6(修改所有的变量)
Collect
Get Started
Collect
Get Started
Collect
Get Started
Collect
Get Started
评论
0 条评论
下一页