p.s.这是萌新自己自学总结的笔记,如果想学习得更透彻的话还是请去看大佬的讲解
目录
- static修饰符
- 静态变量
- 静态方法
- 工具类
- 工具类的使用例子
- 第一题
- 第二题
- static注意事项
- 继承关系
- 建立继承关系的格式
- 继承的好处及使用场景
- 继承的特点
- 继承体系的设计
- 继承中类的三大要素的访问特点
- 继承中成员变量的访问特点
- 继承中成员方法的访问特点
- 方法的重写
- 继承中成员方法的访问特点
- this和super
- 带有继承结构的标准Javabean类例题
static修饰符
static,翻译过来的意思为静态。static可以用来修饰成员变量,成员方法
被static修饰的成员变量叫做静态变量
被static修饰的成员方法叫做静态方法
静态变量
特点:被这个类所有的对象共享。其不属于某个对象,是属于类的
静态变量是随着类的加载而加载的,是优先于对象出现的
调用方式:
- 类名调用(推荐)
- 对象名调用
静态方法
特点:多用在测试类和工具类当中。javabean类中很少会使用
调用方式:
- 类名调用(推荐)
- 对象名调用
工具类
定义工具类的规则
- 类名见名知意
- 私有化构造方法,为了不让外界创建它的对象
- 方法定义为静态,方便调用
工具类的使用例子
第一题
编写一个工具类ArrayUtil
提供一个工具类方法printArr,用于返回整数数组的内容,返回的字符串格式: [12,15,13,100] (只考虑一维整数数组)
提供这样一个工具方法getAverage,用于返回平均数(只考虑一维浮点型数组)
定义一个测试类Test,调用该工具类的工具方法,并返回结果
工具类
public class ArrayUtil {
private ArrayUtil(){}
public static String printArr(int[]arr){
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length; i++) {
if (i== arr.length-1) {
sb.append(arr[i]);
}
else {
sb.append(arr[i]).append(", ");
}
}
sb.append("]");
return sb.toString();
}
public static double getAverage(double[]arr){
double sum = 0;
for (int i = 0; i < arr.length; i++) {
sum = sum + arr[i];
}
return sum/arr.length;
}
}
测试类
public class Test {
public static void main(String[] args) {
int[]arr = new int[]{1,2,3,4,5};
double[]arr2 = new double[]{1,2,3,4,5};
String string = ArrayUtil.printArr(arr);
System.out.println(string);
double average = ArrayUtil.getAverage(arr2);
System.out.println(average);
}
}
第二题
需求:定义一个集合,用于存储3个学生对象
学生类的属性为:name、age、gender
定义一个工具类,用于获取集合中最大学生的年龄
javabean类
public class Student {
private String name;
private int age;
private char gender;
public Student() {}
public Student(String name, int age, char gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
}
工具类
import java.util.ArrayList;
public class StudentUtil {
private StudentUtil() {}
public static int getMaxAge(ArrayList<Student> list){
int maxAge = list.get(0).getAge();
for (int i = 1; i < list.size(); i++) {
if (maxAge<=list.get(i).getAge()){
maxAge = list.get(i).getAge();
}
}
return maxAge;
}
}
测试类
import java.util.ArrayList;
public class StudentTest {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
Student student1 = new Student("张三",18,'男');
Student student2 = new Student("李四",22,'女');
Student student3 = new Student("王五",20,'男');
list.add(student1);
list.add(student2);
list.add(student3);
System.out.println(StudentUtil.getMaxAge(list));
}
}
static注意事项
静态方法只能访问静态变量和静态方法
非静态的方法可以访问静态变量和静态方法,也可以访问非静态的成员变量和非静态的成员方法
静态方法中没有this关键字
简略来说:
静态方法中只能访问静态
非静态可以访问所有
静态方法中没有this关键字
详细解析看这里
继承关系
继承关系是类与类之间的关系。
比如学生和老师会有人的所有属性以及行为,也会有人所不具有的、特有的属性(比如就读学校、就业学校)和行为(比如在学校学习、在学校教书)。
既然如此,当我们在写类(学生) 和 类(老师) 的时候,可以将他们共有的属性(比如姓名)和行为(比如吃饭)提取出来写在一个新的类 类(人) 里面,而他们所特有的属性和行为就继续放在他们的类里面。这便是继承。
其中类(学生) 和 类(老师) 称为子类,类(人) 称为父类
继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
继承就是子类继承父类的特征和行为,使得子类对象具有父类的方法,或子类从父类继承方法,使得子类具有父类相同的行为。
子类可以得到父类的属性和行为,子类可以继续使用
子类可以在父类的基础上新增其他功能,使得子类更加强大
建立继承关系的格式
使用extends关键字,我们可以让一个类和另一个类建立起继承关系
格式
public class 子类 extends 父类{}
子类也叫派生类;父类也叫基类或超类
继承的好处及使用场景
继承可以把多个子类中的重复代码抽取到父类中,提高了代码的复用性
子类可以在父类的基础上再增加其他的功能,使子类更强大
当类与类之间,存在相同(共性)的内容,并满足子类是父类的一种时,就可以考虑使用继承来优化代码
继承的特点
JAVA只支持单继承、不支持多继承,但支持多层继承
单继承:一个子类只能继承一个直接父类
不支持多继承:子类不能同时继承多个父类
多层继承:子类A继承父类B,父类B可以继承父类C。父类B是子类A的直接父类,父类C是子类A的间接父类
每一个类都直接或间接的继承于Object
.
子类只能使用父类中非私有的成员,可以继承父类的成员变量(不论是否非私有)和非私有的成员方法,但是不能使用继承下来的父类中私有的成员变量。不能继承构造方法。如果父类的成员方法在虚方法表中就可以被继承,否则就不行
以内存图的形式解释原因
继承体系的设计
技巧:画图法
从下往上画,下面为子类,上面为父类
把子类的共性内容抽取到父类中
核心:共性内容抽取;子类是父类的一类
设计继承体系是要从父类开始写
下面为设计继承体系的例子
类(学生)
//设计继承体系
//给定4个学生:A、B、C、D
//暂时不考虑属性,只考虑行为
//按照继承的思想特点进行继承体系的设计
//A:学习、吃饭、玩游戏、emo
//B:学习、吃饭、玩游戏、emo
//C:学习、吃饭、追剧
//D:学习、吃饭、运动
public class Student {
public void eat(){
System.out.println("吃饭!!");
}
public void study(){
System.out.println("学习");
}
}
类(玩游戏和emo的学生)
public class PLAYandEMO__Students extends Student {
private void play(){
System.out.println("玩游戏!!");
}
private void emo(){
System.out.println("emo");
}
}
类(学生C)
public class StudentC {
public void watchTY(){
System.out.println("追剧中······");
}
}
类(学生D)
public class StudentD {
public void exercise(){
System.out.println("运动中...");
}
}
继承中类的三大要素的访问特点
继承中成员变量的访问特点
特点:就近原则:谁离我近,我就用谁
如果没有修饰符的话,先在局部位置找,再在本类成员位置找,再在父类成员位置找,逐级往上
举例
class Fu{
String name = "Fu";
}
class Zi extends Fu{
String name = "Zi";
public void ziShow(){
String name = "ziShow";
System.out.println(name);
}
}
输出
ziShow
当出现了重名的成员变量怎么办?
举例
class Fu {
String name = "张三";
String hobby = "内卷";
}
class Zi extends Fu{
String name = "李四";
String game = "卡拉彼丘";
public void show(){
//如何打印李四
System.out.println(name);
System.out.println(this.name);
//如何打印张三
System.out.println(super.name);
//如何打印内卷
System.out.println(hobby);//先在局部变量位置找,再在成员变量位置找,最后到父类成员变量位置中找
System.out.println(this.hobby);//先在成员变量位置找,再到父类成员变量位置中找
System.out.println(super.hobby);//到父类成员变量位置中找
//如何打印卡拉彼丘
System.out.println(game);
System.out.println(this.game);
}
}
继承中成员方法的访问特点
直接调用时满足就近原则:谁离我近,我就用谁
即先在本类中查找有无该方法,若有就调用本类的该方法,若没有就调用父类中继承下来的该方法
若用super调用就直接到父类中找
举例
public class Test {
public static void main(String[] args) {
Zi zi = new Zi();
zi.eatLunch();
}
}
class Fu {
public void eat(){
System.out.println("吃烧烤");
}
public void drink(){
System.out.println("喝雪碧");
}
}
class Zi extends Fu{
public void eatLunch(){
eat();//这里隐藏了一个this,所以其实这句话应该为 this.eat()
drink();//同理
super.eat();
super.drink();
}
public void eat(){
System.out.println("吃火锅");
}
public void drink(){
System.out.println("喝加多宝");
}
}
输出结果
吃火锅
喝加多宝
吃烧烤
喝雪碧
可以发现**类(zi)里面的eat()和drink()方法其实类(Fu)**里面的eat()和drink()方法重写了一遍得到的,而这我们便叫作方法的重写
方法的重写
当父类的方法不能满足子类现在的需求时,需要进行方法重写
.
书写格式:在继承体系中,子类出现了和父类一模一样的方法声明,我们就称子类这个方法是重写的方法
.
@override重写注解
@override是写在重写后的方法上面,校验子类重写时语法是否正确(虚拟机来校验)
若加上注解后出现红色波浪线,则表示语法错误
建议重写方法都加上@override重写注解,可以提高代码的安全性、可读性
.
方法重写的本质是将父类继承下来的虚方法表中的对应方法进行重写覆盖
虚方法表:类中没有被private、static、final修饰的方法的集合
.
注意事项:
- 重写方法的名称、形参列表必须与父类中的一致
- 子类重写父类方法时,访问权限子类必须大于父类(空着不写<protected<public)
- 子类重写父类时,返回值类型子类必须小于等于父类
- 重写方法时子类和父类尽量保持一致
- 只有被添加到虚方法表里的方法才能被重写
下面为方法重写在设计继承体系时的作用
class TeacherTest {
public static void main(String[] args) {
TeacherA teacherA = new TeacherA();
TeacherB teacherB = new TeacherB();
TeacherC teacherC = new TeacherC();
teacherA.eat();
teacherA.teach();
teacherA.game();
teacherB.eat();
teacherB.teach();
teacherC.eat();
teacherC.teach();
}
}
//=========================================
class Teacher {
//现在有三位老师,只考虑行为
//设计一个继承体系
//老师A:教书(语文) 、吃饭 、打游戏
//老师B:教书(数学) 、吃饭
//老师C:教书(英语) 、吃饭
public void eat(){
System.out.println("吃饭中");
}
public void teach(){
System.out.println("老师在教书");
}
}
//=========================================
class TeacherA extends Teacher{
@Override
public void teach(){
System.out.println("老师在教语文");
}
public void game(){
System.out.println("老师在打游戏");
}
}
//=========================================
class TeacherB extends Teacher{
@Override
public void teach(){
System.out.println("老师在教数学");
}
}
//=========================================
class TeacherC extends Teacher{
@Override
public void teach(){
System.out.println("老师在教英语");
}
}
继承中成员方法的访问特点
父类中的构造方法不会被子类继承,但能通过super调用
.
子类中所有的构造方法默认先访问父类中的无参构造,再执行自己
原因:子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据
因此子类在初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化
.
怎么调用的父类构造方法?
子类构造方法的第一行语句默认都是:super(),不写也存在,且必须在第一行
super() →调用父类的无参构造
如果想调用父类的有参构造,就必须手动写super进行调用
下面为调用父类的无参构造
public class Test1 {
public static void main(String[] args) {
Student1 student1 = new Student1();
}
}
//======================================
class Person{
String name;
String id;
public Person() {
System.out.println("父类的无参构造被调用");
}
public Person(String name, String id) {
this.name = name;
this.id = id;
}
}
//======================================
class Student1 extends Person{
public Student1() {
//子类构造方法中隐藏的super()方法是用来访问父类的无参构造的
super();
System.out.println("子类的无参构造被调用");
}
}
输出
父类的无参构造被调用
子类的无参构造被调用
下面为调用父类的有参构造
public class Test1 {
public static void main(String[] args) {
Student1 student1 = new Student1("张三","001");
System.out.println(student1.name+", "+student1.id);
}
}
//======================================
class Person{
String name;
String id;
public Person() {
System.out.println("父类的无参构造被调用");
}
public Person(String name, String id) {
this.name = name;
this.id = id;
}
}
//======================================
class Student1 extends Person{
public Student1() {
//子类构造方法中隐藏的super()方法是用来访问父类的无参构造的
super();//这一步可以手动书写,程序会自动帮我们写
System.out.println("子类的无参构造被调用");
}
public Student1(String name,String id) {
super(name,id);//需要手动调用父类的有参构造
}
}
输出
张三, 001
this和super
this可以理解为一个变量,表示当前方法调用者的地址值; super代表父类的存储空间
this访问本类构造方法举例
public class Students {
String name;
String id;
String school;
//要求:默认为为AA大学
public Students() {
this(null,null,"AA大学");
//表示调用本类其他构造方法
//这时虚拟机就不会再添加super()。因为其他构造方法开头有隐藏的super()
}
public Students(String name, String id, String school) {
this.name = name;
this.id = id;
this.school = school;
}
}
带有继承结构的标准Javabean类例题
需求:写出带有继承结构的标准Javabean类
1.经理
成员变量:工号、姓名、工资、成就
成员变量:工作(管理别人)、吃饭
2、厨师
成员变量:工号、姓名、工资
成员方法:工作(炒菜)、吃饭