一、static修饰符
1.1 static简介
1.1.1 概述
static是静态修饰符,一般修饰成员。被static修饰的成员属于类,不属于单个这个类的某个对象。
static修饰的成员被多个对象共享。
static修饰的成员属于类,但是会影响每一个对象。
被static修饰的成员又叫类成员,不叫对象的成员。
如下例中国籍变量,所有中国人国籍均应该为中国,不应各自定义各自的国籍,所以可以将国籍定义为static,属于类,被多个对象共享。
1.2 静态的使用方式及加载原理
1.2.1 概述
被static修饰的成员可以并且建议通过类名直接访问。也可以通过某个对象访到属于类的静态成员,原因即多个对象均属于一个类,共享使用同一个静态成员。
格式:
类名.静态成员变量名
类名.静态成员方法名(参数)
对象名.静态成员变量名 ------不建议,出现警告
对象名.静态成员方法名(参数) ------不建议,出现警告
第2章 final关键字
2.1 概述
学习了继承后,我们知道,子类可以在父类的基础上改写父类内容,比如,方法重写。那么我们能不能随意的继承API中提供的类,改写其内容呢?显然这是不合适的。为了避免这种随意改写的情况,Java提供了final
关键字,用于修饰不可改变内容。
-
final: 不可改变,最终的含义。可以用于修饰类、方法和变量。
-
类:被修饰的类,不能被继承。
-
方法:被修饰的方法,不能被重写。
-
变量:被修饰的变量,有且仅能被赋值一次。
final int a = 10; //则a无法被2次赋值
-
注意:
1.我们通常使用public static final来定义静态常量(如接口中的固定修饰符)
2.引用类型的变量用final修饰,是指其所引用的对象不能改变,即该变量引用的地址值不能改变。
2.2 使用方式
2.2.1 修饰类
final修饰的类,不能被继承。
格式如下:
final class 类名 { }
代码:
final class Fu { } // class Zi extends Fu {} // 报错,不能继承final的类
查询API发现像 public final class String
、public final class Math
、public final class Scanner
等,很多我们学习过的类,都是被final修饰的,目的就是供我们使用,而不让我们所以改变其内容。
2.2.2 修饰方法
final修饰的方法,不能被重写。 格式如下:
修饰符 final 返回值类型 方法名(参数列表){ //方法体 }
class Fu2 {
final public void show1() {
System.out.println("Fu2 show1");
}
public void show2() {
System.out.println("Fu2 show2");
}
}
class Zi2 extends Fu2 {
// @Override
// public void show1() {
// System.out.println("Zi2 show1");
// }
@Override
public void show2() {
System.out.println("Zi2 show2");
}
}
2.2.3 修饰变量-局部变量
局部变量——基本类型 基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。代码如下:
public class FinalDemo1 {
public static void main(String[] args) {
// 声明变量,使用final修饰
final int a;
// 第一次赋值
a = 10;
// 第二次赋值
a = 20; // 报错,不可重新赋值
// 声明变量,直接赋值,使用final修饰
final int b = 10;
// 第二次赋值
b = 20; // 报错,不可重新赋值
}
}
思考,如下两种写法,哪种可以通过编译?
写法1:
final int c = 0; for (int i = 0; i < 10; i++) { c = i; System.out.println(c); }
写法2:
for (int i = 0; i < 10; i++) { final int c = i; System.out.println(c); }
根据 final
的定义,写法1报错!写法2,为什么通过编译呢?因为每次循环,都是一次新的变量c。这也是大家需要注意的地方。
2.2.4 修饰变量-实例成员变量
成员变量涉及到初始化的问题,初始化方式有显示初始化和构造器初始化,只能选择其中一个:
-
显示初始化(在定义成员变量的时候立马赋值);
public class Student { final int num = 10; }
-
构造器初始化(在构造器中赋值一次)。
public class Student {
final int num = 10;
final int num2;
public Student() {
this.num2 = 20;
// this.num2 = 20;
}
public Student(String name) {
this.num2 = 20;
// this.num2 = 20;
}
}
被final修饰的常量名称,一般都有书写规范,所有字母都大写。
第3章 抽象类与抽象方法
3.1 抽象类与抽象方法引入
抽象类用来描述一种类型应该具备的基本特征与功能,具体如何去完成这些行为由子类通过方法重写来完成,如:犬科均会吼叫,但属于犬科的狼与狗其吼叫内容不同。所以犬科规定了有吼叫功能,但并不明确吼叫的细节。吼叫的细节应该由狼与狗这样的犬科子类重写吼叫的方法具体实现。
类似上边犬科中的吼叫功能,并不明确实现细节但又需要声明的方法可以使用抽象方法的方式完成。即抽象方法指只有功能声明,没有功能主体实现的方法。
那么犬科就可以定义为抽象类,吼叫方法为抽象方法,没有方法体。
我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类。
-
抽象方法 : 没有方法体的方法。
-
抽象类:包含抽象方法的类。
3.2 抽象类的定义格式
抽象类定义的格式:abstract在class前修饰类
public abstract class 类名 { }
抽象方法定义的格式:abstract在访问权限后,返回值类型前修饰方法,方法没有方法体:
public abstract 返回值类型 方法名(参数);
3.3 抽象类的构造方法
3.3.1 抽象类的构造方法存在的意义
子类构造方法中通过super语句调用抽象父类的构造方法,为抽象父类中的成员变量赋值初始化;而赋好值的成员变量可以被子类的对象使用。
3.4 抽象类的特点及常见疑惑
3.4.1 特点
A:抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。
B:抽象类不可以直接创建对象,原因:调用抽象方法没有意义。
C:只有覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类。
之所以继承抽象类,更多的是在思想,是面对共性类型操作会更简单。
3.4.2 疑虑
A:抽象类一定是个父类,因为抽象类是不断抽取共性需求而来的。
B:抽象类中是可以不定义抽象方法的,此时仅仅是不让该类创建对象,用于某些特殊的设计需要。
C:设计时由具体类抽取出抽象类,而开发阶段应该先定义抽象父类,再根据不同需求由父类定义子类。
3.5 抽象总结
抽象相关的具体定义:
1.抽象类用来描述一种类型应该具备的基本特征与功能,具体如何去完成这些行为由子类通过方法重写来完成
2.抽象方法指只有功能声明,没有功能主体实现的方法
3.具有抽象方法的类一定为抽象类
4.抽象定义关键字:abstract
5.抽象类不能创建对象
6.抽象类也有构造方法
3.6 抽象类的注意事项
关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。
-
抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
-
抽象类中,可以有构造器,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
-
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
-
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
-
抽象类存在的意义是为了被子类继承,抽象类体现的是模板思想。
理解:抽象类中已经实现的是模板中确定的成员,抽象类不确定如何实现的定义成抽象方法,交给具体的子类去实现。
3.7 抽象类存在的意义
抽象类存在的意义是为了被子类继承,否则抽象类将毫无意义,抽象类体现的是模板思想,模板是通用的东西抽象类中已经是具体的实现(抽象类中可以有成员变量和实现方法),而模板中不能决定的东西定义成抽象方法,让使用模板(继承抽象类的类)的类去重写抽象方法实现需求,这是典型的模板思想。
static、abstract、final总结
static 修饰符
特点:
1.修饰成员,此成员不再属于某个对象,而是属于该类
2.修饰块,即是静态块,随着类加载而加载至内存中
3.在内存中独一份
4.非静态的成员方法中可以使用非静态成员,也可以使用静态成员;
静态的成员方法中只可以使用静态成员,不能使用非静态成员。
5.静态方法中,不能使用this
6.静态方法能不能被继承?能不能被重写? 不能
7.一般使用原则:类名.静态成员修饰成员
1.修饰成员属性
2.修饰成员方法
3.修饰代码块
4.修饰内部类
abstract 修饰符 抽象的关键字
1.修饰类 抽象类
1.1 abstract class
1.2 一般当你无法去具体描述一个对象的特征时,可以使用抽象修饰类,抽象类
2.修饰方法 抽象方法
2.1 public abstract void/数据类型 方法名(形参);
2.2 一般对象的行为无法具体描述时,可以使用抽象修饰方法,抽象方法
2.3 抽象方法没有方法体{}
3.特征
3.1 对于抽象类来说,当前类中可以没有抽象方法,而且可以像普通类一样编写(允许有属性、构造方法等成员)
3.2 一旦一个类中有抽象方法时,则当前类必须是抽象类
3.3 抽象类只能当做父类,不能被实例化
3.4 abstract 能否和 final 一起使用呢? 不能使用
3.5 一个类继承了抽象类,要么重写抽象类中所有的抽象方法,要么自己也变成抽象类
final修饰符
1.修饰类 final class,代表是最终的类,不可以再被继承
2.修饰方法 public final 返回值 方法名(){ } , 不可以再被重写
3.修饰属性 初始值不再可以变化(值唯一)
3.1 编译期常量 private final 数据类型 属性名 = 初始值;
3.2 运行期常量 在其所有的构造方法中完成初始值的赋值PS:
final 修饰基本数据类型,代表数值不可以更改
修饰引用数据类型,代表地址不可以更改