7.Java基础知识:面向对象03
1、代码块
1.1 概念:就是使用大括号括起来的一段代码;
1.2 格式
{
代码;
}
1.3 分类(代码块的按照书写位置):
- 局部代码块
书写在一个类的局部位置(函数里面的)的代码块就是局部代码块;
局部代码块,因为定义在函数里面,所以不能直接使用,而是通过调用它所在的函数来执行;
局部代码块,可以用来限定变量的使用范围;
- 成员代码块(根据是否使用static关键字修饰再分类)
静态代码块:静态代码块直接写在类里面,使用static关键字修饰。
构造代码块:也是直接写在类中,但是不需要static关键字修饰。
1.4 类加载顺序
1.5 对象创建过程
2、单例设计
2.1 概念:
单例设计模式:解决的就是在程序运行过程中,一个类最多只能创建一个对象的问题;
2.2 步骤:
1.私有化构造函数;
2.在本类中创建唯一实例对象,使用一个私有静态的成员变量保存
3.对外提供一个公开的静态的函数获供别人获取这个唯一实例对象
2.3 代码实现
- 饿汉式
class Single{
//1.私有化构造函数
private Single(){}
//2.在本类中创建唯一实例对象,使用一个静态私有成员变量保存
private static Single single = new Single();
//3.对外提供一个公开的静态函数
public static Single getInstance(){
return single;
}
}
- 懒汉式
class Single{
//1.私有化构造函数
private Single(){}
//2.在本类中创建唯一实例对象,使用一个静态私有成员变量保存
private static Single single = null;
//3.对外提供一个公开的静态函数
public static Single getInstance(){
if(single == null){
single = new Single();
}
return single;
}
}
3、继承
3.1 概念:
java中的继承指的是使用extends关键字在两个类之间建立的一种关系;其中,继承其他类的类,叫做子类(派生类),被其他类继承的类叫做父类(超类、基类);
3.2 格式
class Fu{}//表示被继承的类,是父类
class Zi extends Fu{}//是继承其他类的类,是子类
3.3 作用:继承,可以使子类直接使用父类的成员
子类继承父类,不能直接使用父类的构造函数和私有成员;
3.4 特点
- 单一继承:一个类只能直接继承一个父类
- 多重继承:一个类的父类还可以拥有父类(不能出现交叉继承)
3.5 成员变量特点:
- 子类可以直接使用父类非私有成员变量
- 子类中写了和父类中同名的成员变量,优先使用子类的
3.6 一般函数特点:
- 子类可以直接使用父类非私有的一般函数
- 子类中写了和父类中一样格式的一般函数,优先使用子类的
3.7 函数重写override
- 概念:
如果在子类中书写了和父类中一样格式的一般函数,直接使用用的是子类中的函数,这种情况叫做子类重写父类函数;一般开发中,如果直接使用父类函数不能满足子类需求,子类就要重写父类函数;
- 应用:
//需求:描述手机这类事物。原始的手机和现代的手机
class OldPhone{ //表示老式手机
//打电话
public void call(String num){
System.out.println("给"+num+"打电话……");
}
//发短信
public void sendMsg(String num,String msg){
System.out.println("给"+num+"发信息,内容是:"+msg);
}
}
class NewPhone extends OldPhone{
//打电话
public void call(String num){
System.out.println("显示来电显示");
System.out.println("给"+num+"视频通话……");
System.out.println("显示通话时长");
}
//发短信
public void sendMsg(String num,String msg){
System.out.println("发送自拍照");
System.out.println("给"+num+"发语音信息,内容是:"+msg);
System.out.println("显示对方是否接收,是否查看");
}
//玩游戏的功能
public void playGame(String name){
System.out.println("再玩"+name);
}
}
class Test{
public static void main(String[] args)
{
//创建手机对象
OldPhone op = new OldPhone();
String num = "18688888888";
//打电话
op.call(num);
//发短信
op.sendMsg(num,"约吗?");
//创建新式手机
NewPhone np = new NewPhone();
//打电话
np.call("18888888888");
//发短信
np.sendMsg(num,"不约,叔叔我们不约!");
//玩游戏
np.playGame("王者荣耀");
}
}
- 函数重写格式:
1、函数名相同;
2、参数列表相同;
3、函数返回值类型相同;
4、是否是静态的相同;
5、子类重写父类函数,访问权限不能比父类低;
- 构造方法的使用
class F{
int a = 10;
public void show(){
System.out.println("a = " + a);
}
public F(){
System.out.println("父类构造函数");
show();
}
}
class Z extends F{
int b = 20;
public void show(){
System.out.println("a = " + a + " ; b = " + b);
}
public Z(){
System.out.println("子类构造函数");
show();
}
}
class Test{
public static void main(String[] args) {
new Z();
}
}
- 输出结果
父类构造函数
a = 10 ; b = 0
子类构造函数
a = 10 ; b = 20
- 结论:
1、子类实例化,只会创建一个对象;
2、子类实例化,会在子类的对象空间中为父类的非静态成员也分配空间;
3、子类构造函数执行时,会通过隐藏步先调用父类构造函数执行;
4、构造函数执行时,哪个类的构造函数,负责为那个类的非静态成员变量显示赋值;
- 子类构造函数的部分问题
1、为什么任何一个类(不包含Object)的构造函数中都需要一个super() 语句?
因为除了Object类,每个类都有一个父类;
父类中的非静态成员变量的赋值操作,只能由父类的构造函数去完成;
所以子类的构造函数中,必须先调用父类构造函数,给父类的非静态成员变量显示赋值;
2、子类构造函数中,this() 和 super() 能否同时存在?
不能;
this()和super()都必须放在子类构造函数的第一行;
子类创建对象时,super()只需要执行一遍;
3、如果父类中没有无参构造函数,子类如何实例化?
两种办法:
1、再父类中添加一个无参构造函数;
2、再子类中手动调用父类有参构造函数
4、如果一个类的构造函数全部私有了,还可以有子类吗?
不可以!
私有的成员,只能再本类中使用;
构造函数全部私有了,子类就没法使用了;
而子类构造函数中必须要调用父类构造函数,现在父类中没有构造函数可调用,所以就不行;
4、final
关键字
final
:最终的,最后的;可以修饰类、变量和函数;
4.1 修饰类
- 格式:直接写在class关键字前面
- 作用:表示这个类不能被继承
4.2 修饰函数
- 格式:直接写在函数的返回值类型前面
- 作用:表示被修饰的函数不能被重写
4.3 修饰变量
- 格式:直接写在变量的数据类型前面
- 作用:表示被修饰的变量中直接保存的数据不能改变
注意:如果修饰的是引用类型的变量,则变量中保存的引用不可改变,但是引用指向的堆内存中的数据可以改变;