JAVA中的代码块与继承
1.面向对象的代码块概述
-
代码块概述
在Java中,使用{ }括起来的代码被称为代码块。 -
代码块分类
- 局部代码块
- 构造代码块
- 静态代码块
- 同步代码块
-
常见代码块的应用
- 局部代码块
在方法中出现;限定变量生命周期,及早释放,提高内存利用率 - 构造代码块
在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
- 局部代码块
-
静态代码块
在类中方法外出现,加了static修饰
在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。(不随着对象加载而加载) -
代码块例题
class Student {
static {
System.out.println("Student 静态代码块"); //1 3
}
{
System.out.println("Student 构造代码块");//3 4 6
}
public Student() {
System.out.println("Student 构造方法");//5 6 5 7
}
}
//第一步从这里开始执行
class StudentDemo {
static {
System.out.println("StudentDemo的静态代码块"); //2 1
}
public static void main(String[] args) {
System.out.println("我是main方法"); //4 2
Student s1 = new Student();//返回去调用对象
Student s2 = new Student();//在调用一次
}
}
输出结果:
StudentDemo的静态代码块
我是main方法
Student 静态代码块
Student 构造代码块
Student 构造方法
Student 构造代码块
Student 构造方法
2.继承
-
继承概述
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。 -
继承格式
通过extends关键字可以实现类与类的继承
class 子类名 extends 父类名 {}
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。 -
继承案例演示
class Fu//创建一个父类
{
String name;
int age;
public void eat() {
System.out.println("play");
}
public void sleep() {
System.out.println("sleep");
}
}
class Zi extends Fu //创建一个子类并继承父类
{
public void playGame() {
System.out.println("read");
}//该方法为子类所特有的,其余成员变量从父类那里继承
}
class Zi2 extends Fu {
public void sing() {
System.out.println("sing");
}
}//一个父类可被多个子类所继承
- 继承的好处和弊端
- 继承的好处
- 提高了代码的复用性
- 提高了代码的维护性
- 让类与类之间产生了关系,是多态的前提
- 继承的弊端
类的耦合性增强了。
- 继承的好处
3.Java中类的继承特点
-
Java中类的继承特点
- Java只支持单继承,不支持多继承。
有些语言是支持多继承,格式:extends 类1,类2,… - Java支持多层继承(继承体系)
- Java只支持单继承,不支持多继承。
-
案例演示
public class MyTest { public static void main(String[] args) { Zi zi = new Zi(); zi.name = "N"; zi.age = 20; zi.sleep(); zi.eat(); zi.playGame(); //没有报错说明继承成功 Zi2 zi2 = new Zi2(); zi2.name = "S"; zi2.age = 23; zi2.sleep(); zi2.eat(); zi2.sing(); System.out.println(zi2.name); System.out.println(zi2.age); //说明一个父类可由多个子类继承
4.继承的注意事项
- 子类只能继承父类所有非私有的成员(成员方法和成员变量)
- 子类不能继承父类的构造方法,但是可以通过super(待会儿讲)关键字去访问父类构造方法。
- 不要为了部分功能而去继承
- 什么时候使用继承
- 当多个类中会大量使用相同的成员变量时,考虑继承
5.继承中成员变量的关系
- 在子类中访问一个变量的查找顺序(“就近原则”)
- 在子类的方法的局部范围找,有就使用
- 在子类的成员范围找,有就使用
- 在父类的成员范围找,有就使用
- 如果还找不到,就报错
6.this和super的区别
- super
- 允许子类局部范围访问父类成员变量,可以无视就近原则
- this和super的区别
- this 代表的是本类对象的引用
- super 代表的是父类存储空间的标识(父类的引用,可以操作父类的成员)
- this和super的使用
- 调用成员变量
- this.成员变量 调用本类的成员变量
- super.成员变量 调用父类的成员变量
- 调用构造方法
- this(…) 调用本类的构造方法
- super(…) 调用父类的构造方法
- 调用成员方法
- this.成员方法 调用本类的成员方法
- super.成员方法 调用父类的成员方法
- 调用成员变量
7.继承中构造方法的关系
-
案例演示
public class MyTest { public static void main(String[] args) { B b = new B(); b.s(); } } class A { public A(int num) { } } class B extends A { public B() {//因为父类是一个有参构造,所以必须super()里边带相应的值来调用父类,且在子类的构造方法中 super(5); } public void s(){ System.out.println("a"); } }
-
子类中所有的构造方法默认 都会访问父类中空参数的构造方法
因为子类会继承父类中的数据,可能还会使用父类的数据。若父类没有初始化,怎么使用
-
每一个构造方法的第一条语句默认都是:super( )
-
Object类是祖先,其他所有类都或多或少继承他。
8.继承中构造方法的注意事项
-
父类如果没有无参构造方法
-
在父类中手动添加一个无参的构造方法
-
子类通过super去显示调用父类其他的带参的构造方法
-
子类通过this去调用本类的其他构造方法(本类其他构造也必须首先访问了父类构造)
-
public class MyTest { public static void main(String[] args) { B b = new B(); } } class A {//有参构造被super调用 public A(int num) { } } class B extends A { public B() { // super() this() 不能在构造方法里面共存 this(5); //调用本类的构造方法。 } public B(int num) { super(num);//调用父类的构造方法 } }
-
-
super(…)或者this(….)必须出现在第一条语句上
9.继承中的问题求解
A:看程序写结果1
class Fu{
public int num = 10;
public Fu(){
System.out.println("fu");
}
}
class Zi extends Fu{
public int num = 20;
public Zi(){
System.out.println("zi");
}
public void show(){
int num = 30;
System.out.println(num);//30
System.out.println(this.num); //20
System.out.println(super.num); //10
}
}
class Test {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
B:看程序写结果2
class Fu {
static {
System.out.println("静态代码块Fu"); //1
}
{
System.out.println("构造代码块Fu"); //3
}
public Fu() {
System.out.println("构造方法Fu"); //4
}
}
class Zi extends Fu {
static {
System.out.println("静态代码块Zi");//2
}
{
System.out.println("构造代码块Zi"); //5
}
public Zi() {
super();
System.out.println("构造方法Zi"); //6
}
}
class Test{
public static void main(String[] args){
Zi z = new Zi(); //请执行结果。
}
}
10.继承中成员方法关系
-
当子类的方法名和父类的方法名不一样的时候
-
当子类的方法名和父类的方法名一样的时候**(约为就近原则)**
- 通过子类调用方法:
- 先查找子类中有没有该方法,如果有就使用
- 在看父类中有没有该方法,有就使用
- 如果没有就报错
- 通过子类调用方法:
11.方法重写
-
方法重写
-
子类中出现了和父类中一模一样的方法声明(方法名,参数列表,返回值类型),也被称为方法覆盖,方法复写。
-
方法重写的应用:
- 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。这样,即沿袭了父类的功能,又定义了子类特有的内容。
-
演示(定义一个手机类)
public class MyTest { public static void main(String[] args) { IPhone iPhone = new IPhone(); iPhone.call(); } } class Phone { public void call() { System.out.println("语音通话功能"); } } class IPhone extends Phone { //我们通过方法重写,可以扩展父类的功能 @Override public void call() { super.call(); //去沿袭父类已经实现好的功能 System.out.println("视频通话功能"); } }
-
-
方法重写的注意事项
-
父类中私有方法不能被重写——因为父类私有方法子类根本就无法继承
-
子类重写父类方法时,访问权限不能更低,所以最好就一致
-
父类静态方法,子类也必须通过静态方法进行重写,其实这个算不上方法重写,子类重写父类方法的时候,最好声明一模一样。
-
演示
权限上:public>protected>缺省的>private
-
12.继承练习:学生和老师
-
继承前
A:案例演示: 使用继承前的学生和老师案例
-
继承后
A:案例演示: 使用继承后的学生和老师案例
13.final关键字
-
final
- 由于继承中有一个方法重写的现象,而有时候我们不想让子类去重写父类的方法.这对这种情况java就给我们提供了一个关键字: final
- final关键字是最终的意思,可以修饰类,变量,成员方法。
-
final修饰特点
- 修饰类: 被修饰类不能被继承
- 修饰方法: 被修饰的方法不能被重写,只能被继承
- 修饰变量: 被修饰的变量不能被重新赋值,变为自定义常量
-
演示
public class MyTest { public final double A = 3.14; //公共静态的常量 public static final boolean FLAG = true; public static void main(String[] args) { final int NUM = 100; //自定义常量 } } class Fu { public final void show() {//此方法不能被重写 System.out.println("fu show"); } } class Zi extends Fu { } //final 修饰类,此类不能被继承。 final class Father { } //报错,不能继承final修饰的类 /*class Son extends Father{ }*/
-
final关键字修饰局部变量
- 基本类型,是值不能被改变
- 引用类型,是地址值不能被改变
- 演示
//final 修饰的是基本数据类型,指的是,值不能再次被改变
final double B = 3.2;
// B=3.6;
//final 修饰引用数据类型,指的是,地址值不能再次被改变。
final Zi zi = new Zi();
// zi = new Zi();