static关键字
概述
static关键字的本义为"静态的",static关键字可以修饰成员变量、成员函数(以后可以用属性代指成员变量,方法代指成员函数),也可以修饰代码块。用于成员变量可实现共享属性,用于成员函数时可用于共享方法。被static关键字修饰的属性/方法/代码块具有以下"特权":
1. 直接从属于类,不需要创建对象即可使用
2. 抢先于构造函数执行
3. 生命周期是从加载类开始到整个程序结束,中途不会被垃圾回收器回收
4. 有且只有一份专属内存
适用场景
一个类中所有对象都有共同属性值或方法
类变量
类中被static关键字修饰的成员变量叫做静态属性,也叫类变量,与成员变量不同,类变量不需要依赖对象,用类名.变量名即可访问非private的类变量。定义格式
访问权限修饰符 static关键字 数据类型 变量名;
类方法
类中被static关键字修饰的成员函数叫做静态方法,也叫类方法,使用类名.函数名(实参列表)即可调用非private的静态函数
定义格式
访问权限修饰符 static关键字 返回值类型 函数名(参数列表) {//函数体}
Notice:静态方法不能访问非静态成员,也就意味着this和super两个指向对象内存地址的指针也都不能出现在静态方法中,因为你无法确定是哪个对象。
静态代码块
静态代码块会随着类的加载一块执行,用于对类变量执行初始化操作,只会执行一次
代码格式
static {
//一系列操作
}
static应用举例
//Human.java
public class Human {
static {
System.out.println("我是基类静态代码块");
}
public Human() {
System.out.println("我是基类构造函数");
}
}
//Student.java
public class Student extends Human {//这个继承用于展示基类和派生类中函数执行的先后顺序
String name;
static String teacher;//假设这个类所有学生的老师都是同一位
//静态代码块:初始化静态属性
static {
System.out.println("我是派生类静态代码块");
teacher = "Jackee";
}
//养成这个习惯,构造函数写一个无参的和一个有参的
public Student() {
//这行隐含了super();
System.out.println("我是派生类的构造函数");
}
public Student(String name) {
//这行隐含了super();
System.out.println("我是派生类的构造函数");
this.name = name;
}
//静态方法
public static void shout() {
System.out.println("一库");
}
}
//User.java
public class User {
public static void main(String[] args) {
Student.shout();//对于静态成员函数,只需要用类名即可调用
Student s = new Student("Reno");
System.out.println(s.name);
System.out.println(s.teacher);
Student s2 = new Student("Irene");
s2.teacher = "Mary";
System.out.println(s2.name);
System.out.println(s2.teacher);
System.out.println(s.teacher);
}
}
执行结果如下
上面的例子是static关键字的"串串烧",帮助大家理解static关键字修饰的东西都有哪些特征
1. 执行顺序:
基类静态代码块->派生类静态代码块->基类构造函数->派生类构造函数
Tips:顺序上静态方法可以穿插在静态代码块后任意位置,因为无论如何,静态代码块都会随着类的加载抢先执行,并且是基类在前,派生类在后。
2. 静态函数不需要创建对象,通过类名访问即可执行
3. 静态属性是所有对象共同属性,非private的静态属性可以经由任意对象访问和修改
static特殊作用
可以实现更好的封装
一个static怎么跟封装扯上关系了呢?static可进一步提升数据安全性,本Reno提到过不需要创建对象即可使用static的方法,想将数据安全性进一步提升,可以这么做
1. 私有化构造函数和属性,使类的属性无法随意赋值,有时可以暴露getter让属性状态为只读
2. 除了getter仅仅暴露静态方法即可
在这本Reno发现一个问题:如果属性和构造函数全都私有化了,这些私有属性不就没用了吗?
可以这样解决:定义时这样的属性直接写死,这些私有属性依然可以被读取,只不过就是改不了。
多态
概述:相同类型的变量在调用相同的方法时呈现出不同的行为特征。函数通过重载可以实现同一函数有不同的执行结果,不过本Reno认为多态是面向对象的一个要素,并且是在继承关系的基础之上,它允许基类引用指向派生类,不需要指定是哪个派生类对象作为参数传递。一定程度上可以代替某些函数重载(有多个函数参数列表包含继承同一个基类的不同派生类对象)。一句话概括起来就是不同的派生类对象接收来自基类的消息时都能响应各自的操作。
如何体现多态这一思想?
1. 基类的引用指向派生类对象
2. 函数参数列表中形式参数为基类对象的引用,调用时传入派生类对象的引用
3. 函数返回值类型为基类对象的引用,返回值接收的是派生类对象的引用
完美地实现面向对象的多态需要三个要素
1. 要有类的继承,且为多个派生类继承同一个基类
2. 要有方法的重写,且多个派生类中重写基类方法时包含的内容各不相同
3. 要有基类的引用指向派生类对象
至于多态的应用举例,时间关系本Reno这次就不展示了,如果上面的描述和总结有误欢迎大家指正,Bye~