JAVA基础-面向对象07
一、代码块
1. 含义: 就是使用大括号括起来的一段代码
格式
{
代码;
}
2.静态代码块
格式
static{
代码;
}
书写位置:
直接书写在类中成员位置;
怎么执行呢?
在类加载的最后一步,自动执行;
类加载,会把类的成员加载到方法区,其中非静态成员加载到非静态区域,静态成员加载到静态区域;
静态成员加载的顺序:
a、首先加载所有静态成员;
b、按顺序给所有静态成员变量赋默认值;
c、按顺序给所有静态成员变量显示赋值和执行静态代码块;
执行完静态代码块,类才算加载完成;
为什么创建对象两次,而静态的东西只执行一遍?
静态代码块在类加载的时候就执行完毕,而类只加载一次;
一般为了保证执行顺序不出错,会把静态代码块写在静态成员变量下边;
静态代码块的作用:
有些工作需要在程序执行之前,在类加载的时候就做,这些工作就可以放到静态代码块中;比如一些数据加载的共工作;
3. 构造代码块
格式:
{
代码;
}
书写的位置:
直接写在类中;
执行时间:
每创建一次对象,都会执行一次构造代码块,而且是在构造函数的代码执行之前;
创建对象时,调用构造函数进栈,执行构造函数中方法体之前,有个隐式三步:
1、执行super();
2、给对象的成员变量显示赋值;
3、执行构造代码块
隐式三步执行结束,才执行构造函数中的代码;
构造代码块的作用:
因为在构造代码块中的代码,在构造函数中都会执行到,所以,可以将所有构造函数中都会执行的代码抽出来,放到构造代码块中;
3. 局部代码块
书写位置:写在函数中;
格式:
{
代码;
}
作用: 限制变量的范围的;
二、类加载额对象创建的过程
1. 类中成员位置能书写的成员
2. 类加载过程
三、单例设计模式
1.单例设计模式介绍
设计模式:就是对一些常见问题进行总结,并针对具体问题给出一套通用的解决办法(强调的是解决问题的思想);在开发中,只要遇到这类问题,就可以直接使用这些设计模式解决问题;
最早起源于建筑领域,在建筑领域把一些问题和经验进行归纳总结,形成一套可以用来在建筑领域解决大多数问题的方案;
后来计算机领域借鉴了建筑领域的设计模式,把计算机领域中经常遇到的问题进行归纳和总结,形成计算机领域23种设计模式;
单例(单态、原子)设计模式:
它主要用来保证一个类在程序从启动到最后结束,这个类的对象只有一个。单例就是保证一个类的对象是唯一的。
生活中的单例:
比如月亮:所有人看到的都是同一个月亮;
总结单例实现的步骤:
1、私有化构造函数;
2、在本类中自己创建本类的唯一实例,为了安全,需要把保存这个实例对象的变量封装起来;
3、要提供一个公开的方法,供别人获取这个实例;
2.单例设计模式的代码实现
饿汉式:
弊端:在类加载的时候,就会创建这个类的唯一实例对象;
如果只是想使用这个类,而非使用这个类的对象,此时要加载这个类,在加载的时候就会创建对象,就会造成内存浪费;
有没有办法,在第一次需要使用这个类的对象的时候,才去创建它的对象呢?
要实现这个目的,可就不能在类加载的时候创建对象;
懒汉式的弊端:在多线程环境不能保证对象的唯一性;
单例设计模式小结:
设计模式:
就是前人总结的针对同一类问题的解决方案;强调的是解决问题的思路;
单例设计模式:
解决一个类在程序中只能有一个唯一实例对象的问题的解决方案;
单例设计模式的实现方式:
1、私有化构造函数;
2、在本类中创建自己的唯一实例对象;
3、提供一个公开的方法供人获取这个唯一实例;
四、面向对象:继承
生活中的继承:继承财产;子承父业;继承爵位;
继承,一般发生在两方之间,其中一方可以拥有另一方的东西;
1. 继承的引入
案例:使用java代码描述人和学生的信息;
思考:如果可以在学生类中直接使用人类中的属性和方法,就不需要自己在写一遍重复的代码了;
如果可以在人和学生类之间建立一个继承的关系,就好了;
2. JAVA中的继承
在java中,使用关键字extends,可以在两个类之间建立一种关系,就是继承;
这种关系,可以让一方拥有另一方的成员;
写法:
class A{}
class B extends A{}
表示在类A和B之间建立了继承的关系,其中,B类继承了A类;
继承其他类的类叫做子类(派生类);被其他类继承的类,叫做父类(超类、基类);
子类可以拥有父类的成员;
继承实例:
继承的使用限制:
a、继承中,子类只能拥有父类非私有的成员;私有成员和构造函数不参与继承;
b、在开发中,虽然在语法上,可以使用extends关键字在任意两个类之间建立继承的关系,
但是开发中一般只在两个类表示的事物具有某种关系时才能使用继承,这种关系就是:
子类描述的事物是父类描述事物的一个特例;如果要描述的事物之间不具有这种关系,要想使用继承来减少代码量,就要分别从这两类事物向上找,找他们共同所属的事物,然后将共同的东西抽出来,放到这个共同的事物中;
3. JAVA的单继承 & 多继承
a. 单一继承
就是一个类,只能直接继承一个父类;
一个父类可以有多个子类;
b。多重继承:
就是一个类可以继承一个父类,这个父类,又可以继承其他父类;
4. 继承中的成员变量
a. 子类直接拥有父类非私有成员变量
b. 子类中可以定义和父类中同名的成员变量
如果子类中定义了和父类中同名的成员变量,在子类对象中使用的是子类的成员变量;
一般在开发中,如果父类定义了成员变量,子类中都不要再重复定义;
5. 继承中的成员方法 & 方法的重写(overRide)
a. 子类直接拥有父类非私有成员方法
b. 子类中可以定义和父类同样的成员方法
父类中定义了成员函数,一般在子类中,根据需要都会在定义一遍;
c. 方法的重写
如果在子类中定义了和父类中一样的成员函数,在子类对象中使用的就是子类中定义的函数,这种情况叫做方法的重写(覆写);
d. 重写的应用
1 /* 2 需求:描述手机这类事物。原始的手机和现代的手机 3 */ 4 class OldPhone 5 { 6 //打电话 7 void call(String num){ 8 System.out.println("给"+num+"打电话"); 9 } 10 //发短信 11 void sendMsg(String num,String msg){ 12 System.out.println("给"+num+"发短信:"+msg); 13 } 14 } 15 16 //现代手机 17 class NewPhone extends OldPhone 18 { 19 //打电话 20 void call(String num){ 21 System.out.println("来电显示:"+num); 22 System.out.println("显示图片:"+num); 23 super.call(num); 24 } 25 26 //发短信 27 28 //玩游戏 29 void playGame(){ 30 System.out.println("玩游戏"); 31 } 32 } 33 34 class PhoneTest 35 { 36 public static void main(String[] args) 37 { 38 NewPhone np = new NewPhone(); 39 np.call("18888881688"); 40 41 } 42 }
问题:为什么需要重写?
因为父类的功能不一定适合子类的要求,所以要在子类中对父类的功能进行重写;
如果在子类对象中重写了父类的方法,然后要使用父类的方法,就需要使用super关键字;
e.重写注意事项
在子类中写父类中方法时,为了避免格式上的错误,最安全的办法,是直接将父类的方法复制粘贴到子类中,然后修改方法体代码;
f. overload 和override的区别
方法重载(overload):
在同一个类中,可以定义多个名称相同、参数列表不同的函数,叫做方法的重载(和方法的返回值类型无关)
方法重写(override):
在继承中,子类可以定义和父类一样的方法,在子类对象中使用的是子类中定义的方法,这叫做方法的重写;
6. 继承中构造方法的调用
7. 子类实例化的过程
子类创建对象时,会调用子类构造函数,在构造函数执行的时候,会先去调用父类的构造函数;
在父类的构造函数执行后,子类构造函数继续执行隐士三部的后两步,然后执行构造函数的代码
8.子类构造函数的注意事项
a. 为什么任何一个类(不包含Object)的构造函数中都需要一个super() 语句?
因为任何一个类(不包括 OBJECT)都要继承一个类,在继承中,子类可以直接使用父类的私有成员变量,而父类的成员变量的初始化,需要通过父类的构造函数来进行。
所以在子类的构造函数中都要限制性父类的构造函数。
b. 类构造函数中,this() 和 super() 能否同时存在?
不能,因为this()和super()在一个构造函数中必须处于第一行位置
如果一个构造函数中有this(),就没有隐式三步,隐式三步在this语句嗲用的那个构造函数中。
c.如果父类中没有无参构造函数,子类如何实例化?
调用super(),但是父类没有无参构造
解决:1.在父类中添加无参构造2.在子类中手动嗲用有参构造
d.如果一个类的构造函数全部私有了,还可以有子类吗?
不能,因为私有的构造函数,只能咋本类中自己使用,子类如果继承该类,那么子类的构造函数就无法调用父类的构造函数,即报错