Object
Object: 是所有对象的直接或间接父类
该类中定义了所有对象的功能
如果自定义类中也有比较相同的功能,没有必要重新定义
只要沿袭父类中的功能,建立自己特有比较内容即可,这就是覆盖
1.内部类
1.内部类的访问规则
1)内部类可以直接访问外部类中的成员,包括私有
之所以可以访问外部类中的成员,是因为内部类中持有了一个外部类的引用, 格式 外部类名.this
2)外部类要访问内部类,必须建立内部对象
直接访问内部类中的成员Outer.Inner in = new Outer().new Inner();
2.访问格式:
当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类。
格式:外部类名.内部类名 变量名 = 外部对象.内部对象;
Outer.Inner in = new Outer().new Inner();
3.当内部类在成员位置上就可以被成员修饰符所修饰
比如:private 将内部类在外部类中进行封装
static :内部类就具备了静态特性 当内部类被静态修饰后只能访问外部类中的静态成员,出现了访问局限
在外部其他类中如何直接访问static内部类的非静态成员呢?
new Outer.Inner() .function();
在外部其他类中如何直接访问static内部类的静态成员呢?
Outer.Inner.function();
4.注意:当内部类中定义了静态成员,该内部类必须是static的
当外部类中的静态方法访问内部类时,内部类也必须时static的。
5.当描述事物时:事物的内部还有事物,该事物用内部类来描述
因为内部事务在使用外部事物的内容。
匿名内部类
1.匿名内部类其实就是内部类的简写格式
2.定义匿名内部类的前提
内部类必须是继承一个类或者实现接口
3.匿名内部类的格式:new 父类或者接口(){定义子类的内容}.fuction;
4.其实匿名内部类就是一个匿名子类对象,而且这个对象有点胖 。可以理解为带内容的对象
5.匿名内部类中定义的方法最好不要超过3个。
2.异常
1.异常:就是程序在运行时出现的不正常情况
异常的由来:问题也是现实生活中的一个具体事物,也可以通过java的类的形式进行描述,并封装成对象。
其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分:两种 :一种是严重的问题 一种是非严重的问题
对于严重的问题,java通过Error类进行描述 ,对于Error一般不编写针对性的代码对其进行处理
对于非严重的,java通过Exception类进行描述 ,对于Exception可以通过使用真对象的处理方式进行处理
无论Error或者Exception都具有一些共性的内容
比如:不正常情况的信息,引发原因等
2.异常的处理
java提供特有的语句进行处理
try{需要被检测的代码 } catch(异常类 变量(Exception e)){处理异常的代码(处理方式)} finally{一定会执行的语句}
e.printStackTrace();//打印异常详细信息,打印异常的堆栈的跟踪信息
3.对捕获到的异常对象进行常见方法进行操作
对多异常的处理:
1.声明异常时建议声明更为具体的异常,这样处理的可以更具体
2.对方声明几个异常,就对应几个catch块
如果多个catch块中的异常出现继承关系,父类以后吃那个catch块放在最下边
因为项目中会出现特有的问题 而这些问题并未被Java所描述并封装为对象
所以对于这些特有的问题可以按照java的对问题封装的思想
将特有的问题,进行自定义的异常封装
自定义异常:
需求:在本程序中,对于除数是-1,也是错误的是无法进行运算的。
那么就需要对这个问题进行自定义的描述
当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作
要么在内部try catch
要么在函数上声明让调用者处理
一般情况在 函数内部出现异常 函数上需要声明
发现打印的结果中只有异常的名称,却没有异常的信息。
因为自定义的异常并未定义信息
如何定义异常信息呢?
1.class FushuException extends Exception{
如何定义异常信息呢?
复写父类的
/*
private String msg;
FushuException(String msg){
this.msg = msg;
}
public String getmessage(){
return msg;
}
}
*/
2.如何定义异常信息呢?
因为父类中已经把异常信息的操作都完成了。
所以子类只要在构造时,将异常信息传递给父类通过super语句
那么就可以直接通过getmessage方法获取自定义的异常
class FuShuException extends Exception {
private int value;//错误的负数
FuShuException (String msg,int value){
super (msg);
this.value = value;
}
public int getValue(){
return value;
}
}
if(b<0){
throw new FushuException();//手动通过throw关键字抛出一个自定义异常对象
}
//自定义异常必须继承Exception
继承Exception的原因
异常类 和 异常对象都被抛出
他们都具备可抛性,这个可抛性时throwable这个体系中独有的特点
只有这个体系中的类和对象才可以被throws 和 throw 操作
throws和throw的区别
throws使用在函数上 throw使用在函数内
class Demo{
int div (int a ,int b)throws FuShuException{
if(b<0)
throw new FuShuException(“出现了除数是负数的情况--/by fushu”,b);
return a/b;
}
}
Exception 中有一个特殊的子类异常RuntimeException运行时异常
如果在函数内容抛出该异常,函数上可以不用声明,编译一样通过
如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过
之所以不用在函数声明,是因为不需要让调用者处理。
当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况。希望停止程序后,对代码进行修正
自定义异常时:如果该异常的发生,无法在继续进行运算,就让自定义异常继承RuntimeException
对于异常分两种
1.编译时被监测的异常 (如果没有被声明编译失败)
2.编译时不被监测的异常(运行时异常,RuntimeException以及其子类)
异常在子父类覆盖中的体现
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类
2.如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常
如果子类方法发生了异常,就必须进行try处理,不能抛出
异常总结:异常是对问题的描述。将问题进行对象的封装
异常体系: Throwable
--Error
--Exception
-- RuntimeException
异常的体系特点:异常体系中的所有类以及建立的对象都具备可抛性
也就是说可以被throw和throws关键字所操作
只有异常体系具备这个特点
throw和throws的用法:
throw定义在函数内部,用于抛出异常对象
throws定义在函数上,用于抛出异常对象,可以抛出多个用逗号隔开。
当函数内容有throw抛出异常对象,并未进行try处理,必须要在函数上声明,都在编译时失败。
注意:RuntimeException除外,也就是说函数内部如果抛出RuntimeException异常,函数上可以不用声明。
如果函数声明了异常。调用者需要进行处理,处理方法可以throws可以try。
异常有两种:
1.编译时被监测异常: 该异常在编译时如果处理(没有抛也没有try),编译失败。该异常被标识,代表这可以被处理。
2.运行时异常(编译时不监测)在编译时,不需要处理,编译器检查 。该异常的发生,建议不处理,让程序停止,需要对代码进行修正。
异常处理语句
try 需要被监测的代码
catch 处理异常的代码
finally 一定会执行的代码
注意 1.finally里通常定义关闭资源代码,因为资源必须被释放
2.finally只有一种情况不会执行 System.exit(0)系统退出 finally里面的代码不会执行
自定义异常 :
定义类继承Exception或者RuntimeException
1.为了让该自定义类具备可抛性
2.让该类具备操作异常的共性方法
当要定义自定义异常的信息时,可以使用父类已经定义好的功能
将异常信息传递给父类的构造函数
class MyException extends Exception{
MyException(String message)
{
super(message);
}
}
自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。
异常的好处:
1.将问题进行封装
2.将正常流程代码和问题处理代码相分离,方便阅读
异常的处理原则:
1.处理方式有两种:try或者throws
2.调用到抛出异常的功能时,抛出几个就处理几个
3.多个catch,父类的catch放到最下面。
4.catch 内,需要定义针对性的处理方式,不要简单的定义printStackTrace,输出语句
也不要不写
当捕获到的异常,本功能处理不了时,可以继续在catch中抛出
try{throw new Aexception() }
catch(AException e){ throw e}
如果该异常处理不了,但并不属于该功能的异常
可以将异常转换后,在抛出和该功能相关的异常。
或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去
当调用者知道,并处理,也可以将捕获异常处理后,转换新的异常
try{throw new Aexception() }
catch(AException e){
//对AException异常的处理
throw new BException();
}
比如:汇款的例子
异常的注意事项:
在子父类覆盖时,
1.子类抛出的异常必须是父类异常的子类或者子集;
2.如果父类或者接口没有异常抛出时,子类覆盖出现异常时,只能try不能抛
线程的安全问题:原因
当多条语句在操作统一线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,
另一个线程参与进来执行,导致共享数据的错误
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行
java对于多线程的安全问题提供了专业的解决方式
就是同步代码块 。
synchronized(对象){需要被同步的代码}
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的获取权,也进不去,因为没有获取锁。
好处:解决了多线程安全问题
弊端:多个线程需要判断锁。较为消耗资源
要保证多线程安全,必须保证synchronized(对象)为一个 为一个锁
如果同步函数被静态修饰后, 使用的锁是什么呢?
通过验证,发现不在是this,因为静态方法中也不可以定义this
静态进内存时,内存中没有本类对象,但是一定有该类对应的字码节对象 类名.class
静态的同步方法使用的锁是该方法所在类的字节码文件对象 类名.class
静态方法不能访问非静态成员
死锁:同步中嵌套同步
线程间通讯
其实就是多个线程在操作统一个资源,但是操作的动作不同
notifyAll();
wait notify() notifyAll()
都使用在同步中,因为要对持有监视器(锁)的线程操作
所以要使用在同步中,因为只有同步才具有锁
为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识她们所操作线程只有的锁
只有同一个锁上的被等待的线程,可以被同一个锁上notify唤醒。
不可以对不同锁中的线程进行唤醒。
也就是说等待和唤醒必须是同一个锁
而锁是可以任意对象,所以可以被任意对象调用的方法定义Object类中