一、类间访问
1.1 package包介绍
包概述
- 包本质上就是文件夹
- 当在IDEA中创建多级包时,通常适用
. 进行分割 - 包的命名一般为公司域名去掉www后的翻转,例如
com.xu.xxx ,且字母都为小写 - 合理的分包可以便于我们后期对代码的管理
- 在IDEA的包下创建类后,会自动在第一行生成package语句,若使用记事本则必须手写
1.2 包的注意事项
- package语句必须是程序的第一条可执行代码,即其余代码不可以写在package语句的上面,否则报错
- 每个java文件中只能拥有一条package语句,若无包名,则可以没有package语句
1.3 类间的访问
- 若在同一个包下,则可以直接用类名的方式使用对应类
- 若在不同包下,则有两种方式访问
- 使用import关键字进行导包
- 相当于把其他包中的类导入本地的命名空间中,导入后可以直接使用类
- 此方法可用于绝大部分情况
- import关键字必须在package关键字下,class关键字之上
- 通过全类名的方式访问
- 全类名即包名+类名
- 此方法可以使用在多个包下出现了相同类名的类,导入操作会导致同一命名空间下的标识符重名;此时就可以使用全类名的方式调用
二、static关键字与代码块
2.1 static关键字介绍
2.2 static修饰的特点
其特点是决定是否使用static关键字进行修饰的判断依据:即是否优先于对象加载且需要被所有对象共享或可以直接通过类名使用而不需要创建对象
具体特点如下:
- 被static修饰的成员(变量和方法),会被该类的所有对象共享
- 随着类的加载而加载,优先于对象存在。(对象需要类加载后,才能创建)
- 既可以通过**类名.**的方式调用,也可以通过对象名.的方式调用
2.3 static关键字注意事项
- 静态方法只能访问静态的成员
- 因为静态方法优先于对象存在,即优先于其他非静态成员存在
- 而非静态成员只有在对象创建后,才可以进行使用
- 非静态方法可以访问静态成员,也可以访问非静态的成员
- 静态方法中是没有this关键字
- 因为static优先于对象加载,而this代表了当前对象的引用
2.4 代码块概述
在java中,使用{} 包裹住的代码被称为代码块,共分为3种:
- 局部代码块(就是方法中的内容)
- 位置:方法中定义
- 作用:限定变量的生命周期,及早释放,提高内存利用率
- 构造代码块(构造对象前会执行的语句)
- 位置:类中方法外定义
- 特点:每次构造方法执行的时候,都会执行该代码块中的代码,并且在构造方法执行前执行
- 作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性
- 静态代码块(可用于提前初始化一些数据)
- 位置:类中方法外定义
- 特点:需要通过static关键词修饰,随着类的加载而加载,并且只执行一次
- 作用:在类加载的时候做一些数据初始化的操纵
三、继承
3.1 继承概述
继承:让类与类之间产生关系(子父类关系),子类可以直接使用父类中非私有的成员
- 注:若子类和父类不在同一个包中,则默认权限修饰符下的成员也无法使用(详情见3.7 权限修饰符)
3.2 继承的原理
-
子类中所有的构造方法默认都会访问父类中无参的构造方法
注:如果我们编写的类,即使没有手动指定父类,系统也会自动继承Object (Java继承体系中的最顶层父类) -
子类对象会在自己的堆内存中开辟一块super区域专门存放继承的父类的数据
几点说明:
- 子类无法直接使用父类的私有成员,但是并不是指不能继承(如图中name age都是私有成员变量)。严格来说只是无法直接使用
- 虽然调用了父类的有参构造,但并没有创建父类对象,只是完成了成员变量的初始化
- 子类对象独有的属性并不存放在"super区"
-
如果父类中没有空参构造方法,只有带参构造方法,该怎么办?(建议有参构造和无参构造都加上)
注:
- this(…)和super(…)都必须放在构造方法的第一行有效语句,因此二者不能共存
- this(…)和super(…)指调用本类对象带参的构造方法和调用父类对象带参构造方法
3.3 继承的格式
继承通过extends实现
- 格式:
public class 子类名 extends 父类名{} - 范例:
public class Child extends Father{} - Father:是父类,也被称为基类、超类
- Child :是子类,也被称为派生类
public class Father {
public void show() {
System.out.println("show方法被调用");
}
}
public class Child extends Father {
public void method() {
System.out.println("method方法被调用");
}
}
public class Demo {
public static void main(String[] args) {
Father f = new Father();
f.show();
Child c = new Child();
c.method();
c.show();
}
}
3.4 继承的好处和弊端
继承的好处:
- 提高了代码的复用性(多个类相同的成员可以放到同一个类中)
- 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
- 让类与类之间产生了关系,是多态的前提
继承的弊端:
- 继承是侵入性的,降低了代码的灵活性
- 增强了代码的藕合性
什么时候使用继承?
- 当类与类之间,存在相同(共性)的内容,并且产生了“is a”(谁是谁的一种)的关系,就可以考虑使用继承,来优化代码
3.5 继承的特点
3.5.1 声明继承的特点
- Java只支持单继承,不支持多继承,但支持多层继承
- 单继承:子类只能继承一个父类
- 多继承:指子类同时继承多个父类
class A extends B,C,D{} - 多层继承:子类A继承父类B,父类B可以继承父类C
class Grandpa {
public void smoke() {
System.out.println("吸烟");
}
}
class Father extends Grandpa {
public void drink() {
System.out.println("喝酒");
}
}
class Son extends Father {
public void perm() {
System.out.println("烫头");
}
}
public class Test {
public static void main(String[] args) {
Son son = new Son();
son.perm();
son.drink();
son.smoke();
}
}
问题:为什么不支持多继承?
- 因为多个父类中相同的方法名会造成冲突
- 而在其他语言中可能会使用深度/广度优先来决定继承的优先级(挺复杂的),但java不支持
3.5.2 成员变量和成员方法的访问特点
成员变量访问特点:
- 在子类方法中访问一个变量
- 子类局部范围找
- 子类成员范围找
- 父类成员范围找
- 不考虑父类的父类
注:
- 如果子父类中,出现了重名的成员变量,通过就近原则,会优先使用子类的。
- 如果一定要使用父类的,可以通过super关键字,进行区分
成员方法访问特点:
3.5.3 super和this关键字对比
关键字 | 访问成员变量 | 访问成员方法 | 访问构造方法 |
---|
this | this.成员变量 访问类的成员变量 | this.成员方法(…) 访问类的成员方法 | this(…)访问本类构造方法 | super | super.成员变量 访问父类成员变量 | super.成员方法(…) 访问父类成员变量 | super(…)访问父类构造方法 |
3.6 方法重写
方法重写概述
- 在继承体系中,子类出现了和父类中一模一样的方法声明(指方法名、返回值和参数列表都相同)
- Override注解,用来检测当前的方法,是否是重写的方法,起到校验的作用
方法重写的应用场景
- 当子类需要父类的功能,而功能主体子类有自己特有内容,可以重写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容
方法重写的注意事项
- 父类中私有方法不能被重写(只能使用非私有部分)
- 父类非静态方法,子类必须通过非静态方法进行重写
- 注:静态方法不能被重写。如果子类中,也存在一个方法声明一模一样的方法,可以理解为,子类将父类中同名的方法,隐藏了起来,并非是方法重写。
- 子类重写父类方法时,访问权限必须大于等于父类权限(public > protected > 默认)
3.7 权限修饰符
修饰符 | 同一个类中 | 同一个包中子类无关类 | 不同包的子类 | 不同包的无关类 |
---|
private | √ | | | | 默认 | √ | √ | | | protected | √ | √ | √ | | public | √ | √ | √ | √ |
说明:
- private关键字修饰的成员只有在同一个类中才能访问
- 默认的权限修饰(什么都不写)的成员,只有在同一个包中才能访问
- protected关键字修饰的成员,只有不同包的无关类 不能 直接访问
- public关键字修饰的成员可以随意访问
四、抽象类与final关键字
4.1 抽象类概述
需求:定义猫类(Cat)和狗类(Dog)
猫类成员方法:eat(猫吃鱼)drink(喝水…)
狗类成员方法:eat(狗吃肉)drink(喝水…)
- 此时可抽取共性的特点创建Animal类,但是eat()方法两个子类并不相同,此时要声明抽象类
- 抽象方法的定义格式:
- public abstract 返回值类型 方法名(参数列表);
- 抽象类的定义格式:
- public abstract class 类名{}
4.2 抽象类的注意事项
- 抽象类不能实例化
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 可以有构造方法
- 抽象类的子类
- 要么重写抽象类中的所有抽象方法
- 要么也是抽象类(但是意义不大)
4.3 抽象设计模式
设计模式(Design pattern)
- 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
- 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码的可靠性、程序的重用性
模板设计模式
- 把抽象类整体就可以看做成一个模板
- 模板中不能决定的东西定义成抽象方法
- 让使用模板的类(继承抽象类的类)去重写抽象方法实现需求
小结:模板设计模式的优势,模板已经定义了通用结构,使用者只需要关心自己需要实现的功能即可
4.4 final关键字
- 模板方法一般都是去定义骨架(结构),是不允许更改的
- final关键字是最终的意思,可以修饰(方法,变量,类)
final修饰类、方法、变量的效果
-
final修饰类:表名该类是最终类,不能被继承(不能有子类,但是可以有父类) -
final修饰方法:表明该方法是最终方法,该方法不能被重写 -
final修饰变量:表明该变量是一个常量,不能再次赋值
- 变量是基本类型,不能改变的是值
- 变量是引用类型,不能改变的是地址值,但地址里面的内容是可以改变的
|