《黑马Java零基础视频教程精华部分》系列文章目录
黑马Java零基础视频教程精华部分_1_JDK、JRE、字面量、JAVA运算符
黑马Java零基础视频教程精华部分_2_顺序结构、分支结构、循环结构
黑马Java零基础视频教程精华部分_3_无限循环、跳转控制语句、数组、方法
黑马Java零基础视频教程精华部分_4_对象、封装、this关键字、构造方法、对象内存图、成员变量、局部变量、标准JavaBean
黑马Java零基础视频教程精华部分_5_面向对象综合练习
黑马Java零基础视频教程精华部分_6_字符串
黑马Java零基础视频教程精华部分_7_ArrayList集合
黑马Java零基础视频教程精华部分_8_学生管理系统
黑马Java零基础视频教程精华部分_9_面向对象进阶(1)_static、继承
黑马Java零基础视频教程精华部分_10_面向对象进阶(2)_多态、包、final、权限修饰符、代码块
黑马Java零基础视频教程精华部分_11_面向对象进阶(3)_抽象类、接口、适配器
黑马Java零基础视频教程精华部分_12_面向对象进阶(4)_内部类
一、static(表示静态) 是Java中的一个修饰符,可以修饰成员方法,成员变量
1、静态变量
被static修饰的成员变量,叫做静态变量
如果我们定义的同一个班级的Student中如果有一个属性为老师姓名,所有同学的这个属性因为都是一个班的同学所以相同,那么我们不必在新建对象时候一个个赋值,可以使用静态变量的方式。
public class Student {
//属性:姓名 年龄 性别
//新增:老师的姓名
private String name;
private int age;
private String gender;
public static String teacherName;
}
特点:被该类的所有对象共享。不属于对象,属于类。随着类的加载而加载,优先于对象存在。
调用方式:(1)类名调用(推荐) (2)对象名调用
2、静态变量底层原理
- 程序刚启动时,首先main方法入栈。
- 在main的第一行代码中用类名Student调用了静态变量teacherName,这是就用到了Student这个类,这时候就会把Student类的字节码文件加载到方法区,并在内存当中创建了一个单独存放静态变量的空间—静态区,这时候teacherName的默认值为NULL。注意此时内存中没有对象,所以静态变量优先于对象而出现,其他用static修饰的东西也有这个特性。然后给teacherName赋值“阿玮老师”。
- 之后第二行代码有new Student(),即可创建一个Student对象放入内存中,之后student对象需要teacherName时,从静态区中读取即可。
3、static静态方法
被static修饰的成员方法,叫做静态方法
特点:
- 多用在测试类和工具类中
- Javabean类中很少会用
调用方式:
- 类名调用(推荐)
- 对象名调用
4、工具类、测试类、Javabean类
Javabean类:用来描述一类事物的类。比如,Student,Teacher,Dog,Cat等。
测试类:用来检查其他类是否书写正确,带有main方法的类,是程序的入口。
工具类:不是用来描述一类事物的,而是帮我们做一些事情的类。特点:类名见名知意,私有化构造方法(构造方法一旦私有,那么外界不能创建这个类的对象),方法都定义为静态的(方便调用)。
5、static注意事项
- 静态方法只能访问静态变量和静态方法
- 非静态方法可以访问静态变量或者静态方法,也可以访问非静态的成员变量和非静态的成员方法
- 静态方法中是没有this关键字
从代码层面
理解1和3:在一般的一个类中的普通成员函数,其实自带一个参数就是调用者的地址值,如下图所示,s1.show1()在执行时,就自动将s1的地址传入了函数show1中,然后show1如果要输出属性,就可以知道输出的是s1的属性,而再调用show2时候,默认还是show1参数的那个地址来调用show2(下图可以省略show2前面的this,一般这个this是隐含的)。
而静态方法的参数中,没有自带那个this参数,我们也不能自己设置,所以静态方法中使用this是不可以的,计算机不知道this指的是谁。
理解2:为什么非静态方法(里面带着对象的地址)可以访问所有呢,因为静态方法除了用类名可以访问,也可以用对象(也就是对象地址)来访问。
从内存层面
理解为什么静态方法只能访问静态变量和静态方法,即不能访问非静态是为什么?
首先不能访问非静态变量是因为,静态方法会比非静态变量先进入内存,那内存中还没有静态方法需要的变量时,显然无法调用,会出现错误。不能访问非静态方法,是因为静态方法中没有对象地址,那么显而易见不知道访问的是哪个对象的方法,会出现错误。
6、重新认识main方法
最后一条中:我们可以在IDEA中通过设置程序实参来体会,如下两图所示。
二、继承
1、为什么会有继承?
首先要知道封装,即对象代表什么,就得封装对应的数据,并提供数据对应的行为。如下图所示,我们进行封装的两个类,他俩包含很多共同的内容。我们的思想一直是要把相同的内容放在同一个地方,所以我们最好把重复的内容写在第三个类中,其余两个类来继承这第三个类即可。
2、实现继承以及好处
- Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起继承关系。
public class student extends Person {}
- Student称为子类(派生类),Person称为父类(基类或超类)。
- 使用继承的好处:可以把多个子类中重复的代码抽取到父类中了,提高代码的复用性。子类可以在父类的基础上,增加其他的功能,使子类更强大。
3、继承需要学习的点
(1)自己设计
什么时候用继承?
当类与类之间,存在相同(共性)的内容,并满足子类是父类中的一种,就可以考虑使用继承,来优化代码。
(2)用别人的
4、继承的特点
Java只支持单继承,不支持多继承,但支持多层继承。
Java中所有的类都默认直接或者间接继承于Object类。
子类只能访问父类中非私有的成员。
5、子类到底能继承父类中的哪些内容
误区1:父类私有的东西,子类就无法继承
误区2:父类中非私有的成员,就被子类继承下来了
误区3:继承与调用画等号。
构造方法都不可被继承
原因很简单,如果可以被继承,那构造方法名(父类名)和类名(子类名)不一致。
成员变量都可被继承,但是父类中私有的不可以被直接调用。
继承的内存图如下所示,在方法区中,在运行Zi z = new Zi()
时,需要把Zi的父类也调入方法区,在堆中开辟内存时同理。
图中红色代码表示代码运行错误。
成员方法能够被添加到虚方法表中,则可以被继承
6、继承中成员变量的访问特点
就近原则:先从所在方法中的局部变量找,没有的话,再从本类中找,没有的话,再从父类中找。
注意:可以通过使用this或者super来改变调用的变量是哪个。
7、继承中成员方法的访问特点
同上,满足就近原则。
方法的重写当父类的方法不能满足子类现在的需求时,需要进行方法重写。其本质是覆盖了自己虚方法表中的方法,如果用了super则去找父类的虚方法表的方法。
书写格式在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法。
@Override重写注解
- @Override是放在重写后的方法上,校验子类重写时语法是否正确。
- 加上注解后如果有红色波浪线,表示语法错误。
- 建议重写方法都加@Override注解,代码安全,优雅!
方法重写注意事项和要求
1.重写方法的名称、形参列表必须与父类中的一致。
2.子类重写父类方法时,访问权限子类必须大于等于父类(暂时了解:空着不写<protected<public
3.子类重写父类方法时,返回值类型子类必须小于等于父类(子类就小于父类,比如子类中的重写函数的返回值的类型是一个Dog累,那么父类的函数的返回值类型可以是Animal类)
4.建议:重写的方法尽量和父类保持一致。
5.添加到虚方法表中的方法才可以被重写。
8、继承中构造方法的访问特点
- 子类不能继承父类的构造方法,但是可以通过super调用
- 子类所有种构造方法的第一行,有一个默认的super();
- 默认先访问父类中无参的构造方法,再执行自己,因为子类中的构造方法可能需要使用父类中定义的变量,不先调用父类的构造函数,则内存中无父类的变量,子类无法调用会出错。
- 如果想要方法文父类有参构造,必须手动书写,在super中添加参数即可。