黑马程序员 面向对象
扫描二维码
随时随地手机看文章
静态代码块
格式:
static
{
状态代码块的执行语句
}
特点:随着类的加载而执行,只执行一次,优先于主函数
用于给类进行初始化
重点:静态的特性,执行顺序
Person p = new Person();
=>JVM
=>栈 main函数
=>栈生成P变量
=>堆加载Person类
=>静态代码块执行
=>堆开辟空间存储属性
=>属性默认初始化
=>构造代码块初始化
=>构造函数初始化
=>P指向生成的Person类,成为对象
1.因为new用到了Person,class所以会先找到Person.class文件并加载到内存中
2.执行该类的static代码块,如果有的话,给Person.class类进行初始化
3.在堆内存中开辟空间,分配内存地址
4.在堆内存中剑灵对象的特有属性,并进行默认初始化
5.对属性进行显示初始化
6.对对象进行构造代码块初始化
7.对对象进行对于的构造函数初始化
8.将内存地址赋值给栈内存中P变量
扩展====>>>>设计模式:解决某一类问题最行之有效的方法
java中23种通用设计模式
单例设计模式:解决一个类在内存中只存在一个对象
1.为了避免其他程序过多建立,先禁止其他程序建立该类对象
2.还为了让其他程序可以访问到该类对象,只好在本类中.自定义一个对象
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式
具体实现 (灵活使用static和private修饰符)
1.将构造函数私有化
2.在类中创建一个本类对象
3.提供一个方法可以获取到该对象
恶汉式>>>>对象静态加载>>>>一般用这个
懒汉式>>>>对象延时加载>>>>存在BUG>>>与CPU处理机制相关
继承:
java只支持单继承,不支持多继承
因为多继承容易带来安全隐患:
当多个父类中定义了功能相同内容不同时子类无法确定运行那个
java其实保留了多继承,并用另一种表现形式来完成>>>多实现
java支持多层继承
父类中的内容是子类中的共性内容
创建对象时只创建最子类的对象即可
>>>>>查阅父类功能,创建子类对象
super超类>>>父类对象的引用
this代表的是本类对象的引用
super代表父类对象的引用
当子类出现和父类一模一样的函数时,子类的函数会覆盖父类的函数
当子类继承父类,沿袭了父类的功能,到子类中
但是子类虽级别该功能,但是内容却和父类不一致
这时,没必要定义新功能,而是使用覆盖,,保留父类的功能,并重写功能
在父类功能上添加内容,可以在重写时使用super关键字保留原内容
子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖
否则会造成语法上的错误
静态只能覆盖静态
public大于默认大于private
重载:阻抗同名函数的参数列表
重写:子父类方法要一模一样
子父类构造函数
在子类对象初始化时,父类的构造函数也会运行
那是因为子类的构造函数默认第一行有一条隐式的语句 super()
super():会访问父类中空参数的构造函数
而且子类中所有的构造函数默认第一行都是super()
子类肯定会访问父类的构造函数
因为父类中的数据,子类可以直接获取,所以子类对象在建立时
需要先查看父类是如何对这些数据进行初始的
所以子类在对象初始化时,要先访问下父类中的构造函数
如果要访问父类中指定的构造函数,可以通过搜东定义super()语句的方式来指定
注意:super语句一定定义在子类构造函数的第一行
this()和super()不能在同时在构造函数当中
因为他们都必须写在第一行
必须要先进行初始
子类所有的构造函数,默认都会访问父类中空参数的构造函数
因为子类每一个构造函数内的第一行都有一句隐式的super()
当父类中没有空参数的构造函数时
子类必须手动通过super语句形式来指定要访问父类中的构造函数
子类中至少会有一个刚转身会访问父类中的构造函数
final关键字(修饰符)>>>>>>最终
可以修饰类,函数,变量
被final修饰的类不可以被继承
为了避免继承后被子类复写
被final修饰的方法不能被复写
被final修饰的变量是一个常量,只能赋值一次
既可以修饰成员变量,也可以修饰局部变量
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性
都给这些值起个名字方便阅读,而这个值不需要改变,所以加上final修饰
注意:常量手写规范,所有字母都大写,如果多个单词组成,单词间_理解
内部类定义在局部位置上时,只能访问该局部被final修饰的局部变量
当多个类中出现相同功能,但是功能内容不同
这时可以进行向上抽取
这时只抽取功能第一,而不抽取功能内容
abstrace>>抽象
抽象方法一定定义在抽象类中
抽象方法和抽象类都必须被abstract关键字修饰
抽象类不可以用new创建对象,因为调用抽象方法没意义
抽象类中的方法要被使用,必须由子类复写所有的抽象方法后,剑灵子类对象调用
如果只覆盖了部分抽象方法,那么该子类还是一个抽象类
抽象类和一般类没有太大的不同
抽象类可以不定义抽象方法,这样做仅仅是不让改类建立对象
模板方法设计模式
模板方法:在定义功能时,功能的一部分是确定的,但是有一部分是不确定的
而确定的部分使用不确定的部分
那么就将不确定的部分抽象
由子类具像化
接口:interface
接口的格式特点:
接口中常见定义:常量,抽象方法
常量:public static final
抽象方法:public abstract
接口中的成员都是public的(共有的)
接口不可以创建对象
需要子类将接口具象化
implements 具像化接口
接口可以被类多实现,这也java是对多继承不支持的转换形式
一个类可以继承一个类以及多个接口
class 子类名 extends 父类名 implements 接口名,接口名........
接口之间可以有继承关系,且接口支持多继承
接口的特点:
对外暴露的规则
程序功能的扩展
可以用来多实现
类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口
接口与接口之间可以有继承关系
多态:可以理解为事物存在的多种体现形态
多态的体现
父类的引用指向了自己的子类对象
父类的引用也可以接收自己的子类对象
多态的前提
必须是类与类之间有关系>>>>继承,实现
通常还有一个前提>>>>存在覆盖
多态的好处
多态的出现大大的提高了程序的扩展性
多态的弊端
提高了扩展性的同时,只能使用父类的引用访问父类中的成员
多态的应用
多态的出现注意代码的特点
可以向上转型,类型提升
也可以强制将父类的引用转换成子类类型
但是父类的对象不能强制转换成子类对象
在多态的应用中,始终是子类在变化
判断某一类型引用指向的对象是什么类型>>>>>>>>>>instanceof
在多态中成员函数的特点
在编译时期,参阅引用型变量所属的类是否有调用的方法,如果有编译通过,没有则失败
在运行时期,参阅对象所属类中是否有调用方法
成员函数在多态调用时,编译看左边,运行看右边
在多态中,成员变量的特点
无论编译和运行,都参考左边(引用类型变量所属的类)
在多态中,成员函数的特点
无论编译和运行都参考左边
上帝>>>>>>>>>--------------Obhect
所有对象的超类(多有对象的直接或者间接父类)
该类中定义的肯定是所有对象都具备的功能
Object类中已经提供了的方法,没有必要重新定义
只要沿袭父类中的功能,建立自己特有内容,即覆盖
内部类
将一个类定义在另一个类里面,对里面那个类就称为内部类(内置类,箱套类)
访问特点:
内部类可以直接访问外部类中的成员,包括私有成员
而外部类要访问内部类中的成员必须要建立内部类的对象
访问格式:
1 =>当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中
可以直接建立内部类对象,
格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象;
Outer.Inner in = new Outer().new Inner();
2 =>单内部类在成员位置上,就可以被成员修饰符所修饰
比如:prinvate 将内部类在外部类中进行封装
static 内部类就具备static的特性
当内部类被static修饰后,只能直接访问外部类中是static成员出现访问局限
在外部类其他类中,如何直接访问static内部类的非静态成员
new Outer.Inner().function()
唉外部其他类中,如何直接访问static内部类的静态成员
Outer.Inner.function()
注意:当内部类中定义了静态成员,该内部类必须是static的
当外部类中的静态方法访问内部类时,内部类也必须是static的
当描述事物时,事物的内部还有事物,该事物用内部类来描述
因为内部事物在使用外部事物的内容
内部类定义在局部时
不可以被成员修饰符修饰
可以直接访问外部类中的成员,因为还持有外部类的引用
但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量(常量)
匿名内部类
匿名内部类其实就是内部类的简写格式
定义匿名内部类的前提:内部类必须是继承一个类或者实现一个借口
匿名内部类的格式:new 父类或接口名(){子类内容}
其实匿名内部类就是一个匿名子类对象
异常
异常的体系
Throwable
|--Error:通常出现大问题如:运行的类不存在或者内存溢出,无法编写针对代码对其处理
|--Exception:在运行时运行出现的一起情况,可以通过try,catch,finally进行针对处理
Error和Exception的子类名都是以父类名作为后缀
异常:就是程序在运行时出现不正常情况
异常的由来:java对不正常的情况的封装
异常的处理(Exception):
try
{
可能出现异常的代码
}
catch(Exception e)
{
出现异常时的处理代码
(对捕获到底异常进行常见出方法操作:e.printStackTrace)
(String.getMessage(),获取异常信息)
}
finally
{
一定会执行的语句
}
在功能上通过throws关键字,在函数上声明该功能有可能出现问题,即声明异常
便于提高安全性,强制让调用处进行处理,不处理编译失败
对多异常的处理
声明异常时,建议声明更为具体的异常,这样可以更具体的处理
声明几个异常,就应该对应有几个catch处理方法
如果多个catch接手的异常出现继承关系时,父类要放最下面
每个catch应该针对接手的异常进行针对性处理
因为项目中会出现特有的问题
而这些问题并未被Java所描述并封装对象
所有对于这些特有的问题可以按照Java的对问题封装的思想
将特有的问题,进行自定义的异常封装
即自定义异常:
自定义异常需要继承于父类异常(Exception类)
可以用throw抛出异常对象
那么就必须要给出对应的处理动作
一般函数类出现异常,函数上要声明
自定义异常你可以自定义异常信息(重写getMessate函数)
只有异常体系(Throwable)中的类和对象才可以被throws和throw抛出
shrows和shrow的区别
shrows使用在函数上,后面跟异常类,可以跟多个,用,隔开
shrow作用在函数内,后面跟的是异常对象
Exception中有一个特殊的子类异常RuntimeException运行异常
如果函数内容抛出该异常,函数上可以不用声明,编译一样通过
如果在函数上声明了异常,调用者可以不用进行处理,编译一样通过
之所以不用再函数上声明,是因为不需要让调用者处理
单该异常发生,希望程序停止因为在运行时,出现了无法继续运算的情况
希望停止程序后,对代码进行修正
自定义异常时,如果该异常的发生,无法再继续运算
就让自定义异常继承RuntimeException
对于异常可分为编译时异常和运行时异常(RuntimeException)
try
{
}
catch
{
处理异常后也可以抛出异常(用于被调用者识别)
}
finally
{
无论如何都会被执行的代码
(通常用于关闭资源.)
}
其他格式
try
{
}
finally
{
}
注:catch是用于处理异常的,如果没有catch就代表异常没有被处理过,
如果该异常是检测 时异常,那么必须声明出去
异常在子父类覆盖中的体现
子类在覆盖父类时,如果父类的方法抛出异常,
那么子类的覆盖方法只能抛出父类的异常或该父类异常的子类(可以不抛异常)
如果父类方法抛出多个异常,子类在覆盖该方法时,只能抛出父类异常的子集
如果父类方法没有异常抛出,子类在覆盖方法是时,不可以抛出异常
子类方法发生了异常,就必须用catch进行处理,绝对不能抛出
包(package)
对类文件进行分类管理
给类提供多层命名空间
写在文件的第一行
类名的全称是 包名.类名
包名所有字母小写
当程序中使用packate时
在编译时的格式为
javac -d 目录名 类名.java
protected(保护权限) 权限修饰符