文章目录
………………………………………………2021.4.23更…………………………………………
1、Static关键字
Static关键字修饰的部分是在当前的类中所有的对象共有的,一旦改变所有会一起改变。
(1)static修饰成员变量
static修饰成员变量,那么这个成员变量将会属于这个类,所有由这个类产生的对象都共同绑定该变量,一旦改变一次就会引发该类的所有对象进行改变。
利用static的成员变量进行构造函数时,可以通过计数器IdCounter来记下new了多少个对象。
(2)static修饰成员方法
static修饰成员方法,那么它就属于静态方法,静态方法属于该类所有。
成员方法必须在创建对象之后才能被使用,静态方法则可以通过类名称直接使用:
对于本类中的静态方法可以省略类名称:
注 意 事 项 : \color{red}注意事项: 注意事项:
- 静态方法只能访问静态变量,不能访问成员变量(因为在内存中先有静态内容,后有非静态内容)
- 不能使用this关键字(因为在创建内容的时候还没有对象,this指针无法指向任何位置)
(3)静态static内存图
(3)静态代码块
当第一次用到本类的时候,静态代码块执行唯一的一次。
用途:一次性的对静态成员变量进行赋值。
2、继承
面向对象编程的三大特征:继承、多态、封装。继承是多态的前提
继承解决的主要问题:共性抽取。
(1)步骤
第一步:定义父类(与普通的类一样)
第二部:定义子类(public class 子类名称 extends 父类名称)
(2)子类和父类的成员变量重名
在子类和父类的属性中,如果成员变量重名,则创建子类时访问有两种方式:
- 直接:直接通过子类对象访问成员变量,等号左边优先,没有则向上找
- 间接:间接通过成员方法访问成员变量,该方法属于谁优先用谁,没有则向上找
(3)区分子类方法中重名的变量、方法
局部变量:直接写
父类中的成员变量:super.num
子类中的成员变量:this.num
先找当前的对象的类中是否有,有则运行,否则向上找。子父类的成员、方法重名时,均采用就近原则。
(4)方法重写、覆写
重写:在继承关系中,子父类的方法名、参数列表均一样。
重载:方法名称一样、参数列表不一样。
方法覆写特点:创建的是对象就优先子类方法。
注 意 事 项 : \color{red} 注意事项: 注意事项:
- @Override可以表示正在进行方法重写,不写只要满足条件也是正确的。
- 子类方法的返回值范围必须≤父类方法的返回值范围
例:所有类的共同父类object类,当父类返回值为object时,子类可以返回String;反之则会报错) - 子类方法的权限修饰符≥父类方法的权限修饰符
public > protected > (default)空着 > private
根据方法重写可以给子类中添加新的内容。
(5)构造方法的访问特点
一、子类构造方法中含有一个默认的super(),所以先调用父类构造,后执行子类构造。
二、子类必须要调用父类的构造方法,不写则赠送一次super()
当父类的构造方法有参数的时候,由于子类构造方法中含有一个默认的super(),没有给父类的构造方法赋参数,所以会报错。
三、子类方法可以通过super关键字来调用父类重载构造
四、super的父类构造调用必须是子类构造方法的第一个语句,且只能使用一次
(6)super关键字访问父类的三种用法
-
一、在子类的成员方法中访问父类的成员变量。
-
二、子类的成员方法访问父类的成员方法。
-
三、子类的构造方法访问父类的构造方法。
(7)this关键字访问本类的三种用法
-
一、在本类的成员方法中访问本类的另一个成员方法。
-
二、在本类的成员方法中访问本类的成员变量。
-
三、在本类的构造方法中访问本类的构造方法。
构造方法的重载调用,this也必须是构造方法的第一个语句,且是唯一的,this、super的构造调用不能同时使用。
3、阻止继承
4、向上转型
Student s = new Student();
Person p = s; // upcasting, ok
Object o1 = p; // upcasting, ok
Object o2 = s; // upcasting, ok
注意到继承树是Student > Person > Object
,所以,可以把Student类型
转型为Person
,或者更高层次的Object
。
5、向下转型
和向上转型相反,如果把一个父类类型强制转型为子类类型,就是向下转型(downcasting)。例如:
Person p1 = new Student(); // upcasting, ok
Person p2 = new Person();
Student s1 = (Student) p1; // ok
Student s2 = (Student) p2; // runtime error! ClassCastException!
Person p = new Person();
System.out.println(p instanceof Person); // true
System.out.println(p instanceof Student); // false
Student s = new Student();
System.out.println(s instanceof Person); // true
System.out.println(s instanceof Student); // true
Student n = null;
System.out.println(n instanceof Student); // false
instanceof实际上判断一个变量所指向的实例是否是指定类型,或者这个类型的子类。如果一个引用变量为null,那么对任何instanceof的判断都为false。
利用instanceof,在向下转型前可以先判断:
Person p = new Student();
if (p instanceof Student) {
// 只有判断成功才会向下转型:
Student s = (Student) p; // 一定会成功
}
下面这两种写方式等效的
Object obj = "hello";
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.toUpperCase());
}
public class Main {
public static void main(String[] args) {
Object obj = "hello";
if (obj instanceof String s) {
// 可以直接使用变量s:
System.out.println(s.toUpperCase());
}
}
}