代码块-继承-方法重写-final
目录
代码块的概述和分类(面试的时候会问,开发不用或者很少用)
-
代码块概述:在Java中,使用{}括起来的代码被称为代码块
-
代码块分类:根据其位置和声明的不同,可以分为局部代码块、构造代码块、静态代码块、同步代码块。
class Student { static { //随着类加载而加载,且执行一次 作用:用来给类初始化,一般用来加载驱动 System.out.println("Student 静态代码块"); //静态代码块 } { //每创建一次对象就会执行一次,优先于构造函数执行 System.out.println("Student 构造代码块"); } public Student() { System.out.println("Student 构造方法"); } } class Demo_student { static { //静态代码块优先于主方法执行 System.out.println("Demo_student静态代码块"); } public static void main(String[] args) { System.out.println("我是main方法"); Student s1 = new Student(); Student s2 = new Student(); } } 输出结果:Demo_student静态代码块 我是main方法 Student 静态代码块 Student 构造代码块 Student 构造方法 Student 构造代码块 Student 构造方法
继承(extends)(掌握)
-
继承的好处:
- 提高代码的复用性
- 提高代码的维护性
- 让类与类之间产生了关系,是多态的前提
-
继承的坏处:
- 类的耦合性增强(父类一改变,会牵连到子类)
-
开发的原则:高内聚,低耦合
- 耦合:类与类的关系
- 内聚:就是自己完成某件事的能力
-
Java中继承特点:
- 只支持单继承,不支持多继承(一个儿子只能有一个爹)
- 支持多层继承(继承体系)
-
继承特殊点:
- 如果想用这个体系的所有功能,用最底层的类创建对象
- 如果想看这个体系的共性功能,看最顶层的类
-
继承的注意事项:
-
子类只能继承父类所有非私有的成员(成员方法和变量)
-
子类不能继承父类的构造方法。但是可以通过super关键字去访问父类构造方法
-
不要为了部分功能而继承
this与super的区别与应用
-
this和super都代表什么?
-
this:代表当前对象的应用
-
super:代表当前对象父类的引用
-
this与super的使用区别
-
调用成员变量
-
this.成员变量——调用本类的成员变量,也可以调用父类的成员变量
-
super.成员变量——调用父类的成员变量
继承中构造方法的注意事项
class Demo_extends {
public static void main(String[] args) {
Son s1 = new Son();
System.out.println("---------------");
Son s2 = new Son("张三",23);
}
}
class Father() {
private String name;
private int age;
public Father() {
System.out.println("Father 空参构造");
}
public Father(String name,int age) {
this.name = name;
this.age = age;
System.out.println("Father 有参构造");
}
public void setName(String name) { //设置姓名
this.name = name;
}
public String getName() { //获取姓名
return name;
}
public void setAge(int age) { //设置年龄
this.age = age;
}
public int getAge() { //获取年龄
return age;
}
}
class Son extends Father {
public Son() {
//super(); 隐藏了一个super()
System.out.println("Son 空参构造");
}
public Son(String name,int age) {
/隐藏了super(); 而不是super(name,age);因为他不知道具体的参数
System.out.println("Son 有参构造");
}
}
//输出结果:Father 空参构造
Son 空参构造
--------------------
Father 空参构造
Son 有参构造
继承中的面试题
class Fu {
public int num = 10;
public Fu() {
System.out.println("fu");
}
}
class Zi extends Fu {
public int num = 20;
public Zi() {
//super();
System.out.println("zi");
}
public void show() {
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(super.num);
}
}
class Test_Extends {
public static void main(Strings[] args) {
Zi z = new Zi();
z.show();
}
}
//输出结果:fu
zi
30
20
10
考察点:在每个构造函数的第一句都会隐藏一个super();
class Test_Extends {
public static void main(String[] args) {
Zi z= new Zi();
}
}
class Fu {
static {
System.out.println("静态代码块Fu");
}
{
System.out.println("构造代码块Fu");
}
public Fu() {
System.out.println("构造方法Fu");
}
}
class Zi extends Fu {
static {
System.out.println("静态代码块Zi");
}
{
System.out.println("构造代码块Zi");
}
public Zi() {
System.out.println("构造方法Zi")
}
}
//输出结果:静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi
考点:代码块和隐藏的super();
过程 :1、jvm调用了main方法,main进栈
2、遇到Zi z = new Zi();会先将Fu.class和Zi.class分别加载进内存,再创建对象,
当Fu.class加载进内存,父类的静态代码块也会随着Fu.class一起加载,
当Zi.class加载进内存,子类的静态代码块会随着Zi.class一起加载
所以第一个输出,静态代码块Fu,第二个输出静态代码块Zi
3、走Zi类的构造方法,因为Java中是分层初始化的,先初始化父类,再初始化子类,
所以先走的父类构造,但是在执行父类构造时,发现父类有构造代码块,构造代码块是优先于构造方法执行的,
所以,第三个输出构造代码块Fu,第四个输出构造方法Fu
4、Fu类初始化结束,子类初始化,第五个输出的是构造代码块Zi,构造方法Zi
方法重写概述及其应用(掌握)
- 方法重写的应用:
-
当子类需要父类的功能,而功能主体子类主体有自己特有的内容时,可以重写父类中的方法。这样既沿袭了父类的功能,又定义了子类特有的内容。
例如:
class Demo {
public static void main(String[] args) {
Ios8 i = new Ios8();
i.siri();
i.call();
}
}class Ios7 { public void call() { System.out.println("打电话"); } public void siri() { System.out.println("speak English"); } } class Ios8 ectends Ios7 { public void sisi() { System.out.println("说中文"); super.siri(); } } //输出结果:说中文 speak English 打电话
-
方法重写的注意事项
- 父类中私有的方法不能被重写
- 因为父类私有方法子类根本就无法继承
- 子类重写父类方法时,访问权限不能更低。
- 最好就一致。
- 父类静态方法,子类也必须通过静态方法进行重写。
- 静态只能覆盖静态。
- 静态只能覆盖静态。
学生和老师的继承完整案列
class Test_Person {
public static void main(String[] args) {
Student s1 = new Student(); //使用无参构造
s1.setName("张三");
s1.setAge(23);
System.out.println(s1.getName() + "------" + s1.getAge());
s1.eat();
s1.study();
System.out.println("-------------------");
Student s2 = new Student("李四",24); //使用有参构造
System.out.println(s2.getName() + "------" + s2.getAge());
s2.eat();
s2.study();
}
}
class Person {
private String name; //姓名
private int age; //年龄
public Person() {} //空参构造
public Person(String name,int age) { //有参构造
this.name = name;
this.age = age;
}
public void setName(String name) { //设置姓名
this.name =name;
}
public String getName() { //获取姓名
return name;
}
public void setAge(int age) { //设置年龄
this.age = age;
}
public int getAge() { //获取年龄
return age;
}
public void eat() {
System.out.println(name + "吃饭");
}
}
class Student extends Person {
public Student() {} //空参构造
public Student(String name,int age) { //有参构造
super(name,age); //访问父类的构造方法
}
public void study() {
System.out.println(this.getName() + "学习"); //this.也可以改为super.
}
}
class Teacher extends Person {
public Teacher() {} //空参构造
public Teacher(String name,int age) {
super(name,age); //访问父类的构造方法
}
public void teach() {
System.out.println(this.getName() + "讲课"); //this.也可以改为super.
}
}
输出结果:张三------23
张三吃饭
张三学习
-------------------
李四------24
李四吃饭
李四学习
final关键字
-
final修饰特点
- 修饰类,类不能被继承——如:final class Father {}
- 修饰变量,变量就变成了常量,只能被赋值一次—— 如:public static final double PI = 3.14;常量命名规范:所有字母大写,多个单词用下划线隔开。
- 修饰方法,方法不能被重写——如:public final void print() {} 该方法不能被子类重写。
-
final关键字修饰局部变量
-
基本类型:是值不能被改变
-
引用类型:是地址值不能被改变,对象中的属性可以改变
final Person p = new Person("张三",23); //p = new Person("李四",24); 报错! 引用类型被final修饰,其地址值不能改变,但是属性可以 p.setName("李四"); p.setAge(24);
-
面试题(掌握)
- 方法重载的面试题
- override和overload的区别?overload能改变返回值类型吗?
- 答:overload可以改变返回值类型,只看参数列表
- 方法重写——子类中出现了和父类中方法声明一模一样的方法。与返回值类型有关,返回值是一致(或者是子父类)的。
- 方法重载——本类中出现的方法名一样,参数列表不同的方法。与返回值类型无关。
- override和overload的区别?overload能改变返回值类型吗?
- 子类对象调用方法的时候:
- 先找子类本身,再找父类。
- 先找子类本身,再找父类。