目录
1. final关键字
概述
final的意思是最终的,不可修改的,用于修饰不可改变的内容。
应用场景
final可以用在类、函数、变量上,如果你不希望它们被修改,把他们定义为final即可。
final修饰类
代码格式
public final class 类名 {
//类体
}
final类的特征
1. final类不可以被继承,这就跟好比一个树形结构中的叶子节点。可以保护类的功能不会被修改,为了防止我们继承Java类库中的类并修改其中的功能,API中有相当一部分的类被定义成了final类。
2. final类与abstract类正好相反,一个不允许被继承,一个必须有非抽象派生类才能用,所以应该不会有哪个憨批同时用final 和 abstract 修饰一个类。
举例
//Leaf.java
public final class Leaf {//这里定义了final类
public void fun() {
System.out.println("做一片叶子,跟着风走");
}
}
final修饰成员函数
代码格式
访问权限修饰符 [static关键字] final 返回值类型 函数名(参数列表) {
//方法体
}
使用场景
对于类中的某些函数你如果不希望它的函数体被继承它的派生类重写,这些函数可以定义为final函数。说白了就是对于一个类中某些行为,告诉派生类要么不做,要么必须按照我规定的流程做。
举例
//Parent.java
public class Parent {
public final void fun() {
System.out.println("你好");
}
}
final函数与abstract函数的区别
1. final函数必须有函数体,abstract函数严禁有函数体
2. final函数严禁被重写,abstract函数必须被重写才能使用
3. final函数规定派生类要么不用这个功能,要么必须按照基类规定的流程去做;abstract函数规定派生类必须做什么,至于怎么做交给派生类自己去定。
final修饰变量
代码格式
访问权限修饰符 数据类型 变量名 = 初始值
相当于C++的const关键字,用final修饰的变量叫做常量,它只能被赋值一次,也就是说初始化之后就不能改了
使用场景(基本数据类型)
如果有些变量的值是固定的,定义为final即可。若为成员变量,则通常与static连用,表示该类的所有对象属性都是一样且固定的。
不过上面的例子可能不太规范,定义常量的规则与标识符命名规则基本相同,唯一不同就是所有字母大写,单词之间用下划线。
对于引用类型,赋值时给到的变量其实都是指针,final关键字可以规定它只可以指向一个内存地址,但指向的内存地址中的内容是可变的。
2. 枚举类
概述:
先看一个例子
public class Season {
public static final int Spring = 1
public static final int Summer = 2
public static final int Autumn = 3
public static final int Winter = 4
}
上面的例子中,用1~4表示春夏秋冬四季,看似可以这样,但是当使用这个类时用于比较可能会有很大的困难,在使用者类中你可能不知道1~4代表什么,而这个类中这些属性的值和数量是固定的。我们可以把这些属性放在枚举类型中,这些属性也升级成一个个实例。我们将实例数量固定且内容固定的类型称为枚举类型。
代码格式
//定义格式
public enum 枚举类名 {
实例1,
实例2
}
//使用格式
枚举类名.实例名
使用场景
实例的内容都固定,并且数量有限。
实例的命名规则
枚举类实例命名规则与常量基本一致,也是支持字母、数字、下划线、美元符号,但所有字母都大写,且单词与单词之间用下划线。
上述示例可以优化成
public enum Season {
SPRING,
SUMMER,
AUTUMN,
WINTER
}
使用枚举类时应注意与C++枚举的不同,C++枚举类在用作比较时可直接用枚举实例名,而Java需要在前面加上枚举类名. 才可以。枚举类的实例可以作为某个类的属性,枚举类属于引用类型,可以赋值,可以比较是否相等,但不能参与计算。
3. 接口初步
什么是接口?
接口是Java中的一种引用类型,与抽象类有几分相似,但是有一定的区别。
接口的作用
给多个类中的相同的成员函数或完全相同的属性确定一个统一的规范。
代码格式
//定义接口
[public关键字] interface 接口名 [extends 父接口名1, 父接口名2, ··· {
//常量属性(开头已经省略默认的public static final)
数据类型 变量名 = 初始值;
//抽象方法(开头已省略默认的public abstract)
返回值类型 函数名(参数列表);
}
//实现接口
public class 类名 [extends 基类名] implements 接口名1, 接口名2, ··· {
//类体
}
注意:当一个类继承基类同时实现接口时先写继承关系再接上实现关系
接口的特点
1. 所有的属性均为公共静态常量,且必须被初始化
2. 所有函数均为公共且抽象的函数
3. 无构造函数且无法创建对象,必须有非抽象类实现它才能用
4. 支持多继承,继承的父接口间逗号隔开
5. 对于实现类,可实现若干个接口
6. 实现接口的类必须重写接口中所有的方法,否则应当定义为抽象类
7. 可利用多态接收实现类的对象(向上转型)
使用场景
当多个类中有部分类包含完全相同的行为时,希望给这些相同的行为定义统一的规范。
小练习(接口的多继承)
按如下要求编写Java程序:
(1)定义接口A,里面包含值为3.14的常量PI和抽象方法double area()。
(2)定义接口B,里面包含抽象方法void setColor(String c)。
(3)定义接口C,该接口继承了接口A和B,里面包含抽象方法void volume()。
(4)定义圆柱体类Cylinder实现接口C,该类中包含三个成员变量:底圆半径radius、
圆柱体的高height、颜色color。
(5)创建主类来测试类Cylinder。
//A.java
public interface A {//定义接口A,里面有圆周率常量和计算面积的函数
double PI = 3.14;
double area();
}
//B.java
public interface B {//定义接口B,里面有设置颜色的函数
void setColor(String c);
}
//C.java
public interface C extends A, B {//接口C继承A和B,里面有继承的圆周率常量,以及计算面积、设置颜色的函数,自身包含输出体积的函数
void volume();
}
//Cylinder.java
public class Cylinder implements C {//Cylinder实现接口C
double radius;
double height;
String color;
public Cylinder() {}
public Cylinder(double radius, double height, String color) {
this.radius = radius;
this.height = height;
this.color = color;
}
@Override
public void volume() {
System.out.println("圆柱体的体积是" + (height * area()));
}
@Override
public double area() {
return PI * radius * radius;
}
@Override
public void setColor(String c) {
color = c;
}
}
//CylinderTester.java
public class CylinderTester {
public static void main(String[] args) {
Cylinder c = new Cylinder(7.1, 3.0, "Red");
c.volume();
}
}