JAVA基础再回首(七)——final关键字、抽象类abstract、接口interface、权限修饰符、导包
没有到不了的明天。
嬉皮笑脸面对人生的难。
相信自己,不然你什么都做不了。
final关键字
- final关键字是最终的意思,可以修饰类,成员变量,成员方法。
- 修饰类,类不能被继承
- 修饰变量,变量就变成了常量,只能被赋值一次
- 修饰方法,方法不能被重写
我们可以写一个Demo来验证一下final关键字
class Fu {
public int num = 10;
public final int num2 = 20;
/*
public final void show() {
}
*/
}
class Zi extends Fu {
// Zi中的show()无法覆盖Fu中的show()
public void show() {
num = 100;
System.out.println(num);
//无法为最终变量num2分配值
//num2 = 200; //打开注释会报错
System.out.println(num2);
}
}
public class FinalDemo{
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
输出结果:
100
20
那么final在继承中如何体现呢?
由于继承中方法有一个现象:方法重写。所以,父类的功能就会被子类覆盖掉。有时候为了不让子类去覆盖掉父类的功能,只能让他用,所以,针对这种情况,java就提供了一个关键字:final。
class Fu {
public final void show() {
System.out.println("这里是绝密资源,任何人都不能修改");
}
}
class Zi extends Fu {
// Zi中的show()无法覆盖Fu中的show()
// public void show() {
// System.out.println("这是一堆垃圾");
// }
}
public class FinalDemo{
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
输出结果:
肯定是父类中的输出结果了。
抽象类(abstract)
概述:
动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的。
我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类。
- 抽象类特点
- 抽象类和抽象方法必须用abstract关键字修饰
- 格式
- abstract class 类名 {}
- public abstract void eat();
- 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
- 抽象类不能实例化
- 因为它不是具体的。
- 那么,抽象类如何实例化呢?
- 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
- 抽象类的子类
- 如果不想重写抽象方法,该子类是一个抽象类。
- 重写所有的抽象方法,这个时候子类是一个具体的类。
- 抽象类和抽象方法必须用abstract关键字修饰
abstract class Animal {
//抽象方法
//public abstract void eat(){} //空方法体,这个会报错。抽象方法不能有主体
public abstract void eat();
public Animal(){}
}
//子类是抽象类
abstract class Dog extends Animal {}
//子类是具体类,重写抽象方法
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
}
输出结果:猫吃鱼
- 抽象类的成员特点:
- 成员变量:既可以是变量,也可以是常量。
- 构造方法:构造方法不能被实例化。所以构造方法的特点是:用于子类访问父类数据的初始化。
- 抽象类的成员方法特性:
- 可以有抽象方法,强制要求子类做的事情。
- 也可以有非抽象方法,子类继承的事情,提高代码复用性。
abstract class Animal {
public int num = 10;
public final int num2 = 20;
public Animal() {}
public Animal(String name,int age){}
public abstract void show();
public void method() {
System.out.println("method");
}
}
class Dog extends Animal {
public void show() {
System.out.println("show Dog");
}
}
public class AbstractDemo {
public static void main(String[] args) {
//创建对象
Animal a = new Dog();
a.num = 100;
System.out.println(a.num);
//a.num2 = 200;
System.out.println(a.num2);
System.out.println("--------------");
a.show();
a.method();
}
}
输出结果:
我们学习了抽象方法,但是让我有两个疑惑的问题,不知道你们是不是也同样疑惑,我给大家解答一下。
一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
答案肯定是可以的,意义就是为了不让创建对象。
abstract不能和哪些关键字共存?
private冲突、final冲突、static无意义
下面我们实例一个Demo
public class AbstractDemo {
public static void main(String[] args) {
Father.methods();
}
}
abstract class Father{
//public abstract void show();
//非法的修饰符组合: abstract和private
//private abstract void show();
//非法的修饰符组合 abstract和final
//final abstract void show();
//非法的修饰符组合abstract和static
//static abstract void show();
public static void methods() {
System.out.println("method");
}
}
class Son extends Father {
public void show() {}
}
接口(interface)
- 接口用关键字interface表示
- 格式:interface 接口名 {}
- 类实现接口用implements表示
- 格式:class 类名 implements 接口名 {}
- 接口不能实例化
- 那么,接口如何实例化呢?
- 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态(下一节讲)。
- 接口的子类
- 可以是抽象类。但是意义不大。
- 可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
//定义动物培训接口
interface AnimalTrain {
public abstract void jump();
}
//抽象类实现接口
abstract class Dog implements AnimalTrain {
}
//具体类实现接口
class Cat implements AnimalTrain {
public void jump() {
System.out.println("猫可以跳高了");
}
}
public class InterfaceDemo {
public static void main(String[] args) {
//AnimalTrain是抽象的; 无法实例化
//AnimalTrain at = new AnimalTrain();
//at.jump();
AnimalTrain at = new Cat();
at.jump();
}
}
输出结果:猫可以跳高了
- 接口成员特点
- 成员变量;只能是常量,并且是静态的。
- 默认修饰符:public static final
- 建议:自己手动给出。
- 构造方法:接口没有构造方法。因为接口主要是扩展功能的,而没有具体存在
- 成员方法:只能是抽象方法。
- 默认修饰符:public abstract
- 建议:自己手动给出。
interface Inter {
public int num = 10;
public final int num2 = 20;
public static final int num3 = 30;
//错误: 需要<标识符>,接口没有构造方法
//public Inter() {}
//接口方法不能带有主体
//public void show() {}
//abstract void show(); //默认public
public void show(); //默认abstract
}
class InterImpl extends Object implements Inter {
public InterImpl() {
super();
}
@Override
public void show() {
}
}
public class InterfaceDemo {
public static void main(String[] args) {
//创建对象
Inter i = new InterImpl();
System.out.println(i.num);
System.out.println(i.num2);
//i.num = 100;
//i.num2 = 200;
//System.out.println(i.num); //无法为最终变量num分配值
//System.out.println(i.num2);//无法为最终变量num2分配值
System.out.println(Inter.num);
System.out.println(Inter.num2);
}
}
输出结果:
10
20
10
20
类与类,类与接口以及接口与接口的关系
觉得他们的关系好复杂,快看晕了,没关系,我们逐个学习
- 类与类:
- 继承关系,只能单继承,可以多层继承。
- 类与接口:
- 实现关系,可以单实现,也可以多实现。
- 并且还可以在继承一个类的同时实现多个接口。
- 接口与接口:
- 继承关系,可以单继承,也可以多继承。
interface Father{
public abstract void show();
}
interface Mother {
public abstract void show2();
}
interface Sister extends Father,Mother {
}
class Son extends Object implements Father,Mother {
public void show() {
System.out.println("show son");
}
public void show2() {
System.out.println("show2 son");
}
}
public class InterfaceDemo {
public static void main(String[] args) {
//创建对象
Father f = new Son();
f.show();
//f.show2(); //报错
Mother m = new Son();
//m.show(); //报错
m.show2();
}
}
输出结果:
show2 son
show son
上面我们学习了抽象类,又学习了接口。那么他们之间有什么区别呢?我们继续开车…
抽象类和接口的区别
成员区别
- 抽象类:
- 成员变量:可以变量,也可以常量
- 构造方法:有
- 成员方法:可以抽象,也可以非抽象
- 接口:
- 成员变量:只可以常量
- 成员方法:只可以抽象
- 抽象类:
关系区别
- 类与类
- 继承,单继承
- 类与接口
- 实现,单实现,多实现
- 接口与接口
- 继承,单继承,多继承
- 类与类
- 设计理念区别
- 抽象类
- 被继承体现的是:”is a”的关系。
- 抽象类中定义的是该继承体系的共性功能。
- 接口
- 被实现体现的是:”like a”的关系。
- 接口中定义的是该继承体系的扩展功能。
- 抽象类
权限修饰符
- 修饰符:
- 权限修饰符:private,默认的,protected,public
- 状态修饰符:static,final
- 抽象修饰符:abstract
- 类:
- 权限修饰符:默认修饰符,public
- 状态修饰符:final
- 抽象修饰符:abstract
- 用的最多的就是:public
- 成员变量:
- 权限修饰符:private,默认的,protected,public
- 状态修饰符:static,final
- 用的最多的就是:private
- 构造方法:
- 权限修饰符:private,默认的,protected,public
- 用的最多的就是:public
- 权限修饰符:private,默认的,protected,public
- 成员方法:
- 权限修饰符:private,默认的,protected,public
- 状态修饰符:static,final
- 抽象修饰符:abstract
- 用的最多的就是:public
- 除此以外的组合规则:
- 成员变量:
- public static final
- 成员方法:
- public static
- public abstract
- public final
- 成员变量:
最后我们在学一个小知识点——>导包
导包
- 导包概述
- 不同包下的类之间的访问,我们发现,每次使用不同包下的类的时候,都需要加包的全路径。比较麻烦。这个时候,java就提供了导包的功能。
- 导包格式
- import 包名;
- 注意:
- 我们用那个报就导那个包。
那么,package,import,class有没有顺序关系?
答案是肯定有关系。
package > import > class
Package:只能有一个
import:可以有多个
class:可以有多个,以后建议是一个
今天我们就学到这里,明天我们来学习多态。
最后呢,欢迎有兴趣的同学加我朋友的QQ群:555974449
群主呢,也就是我在第一篇博客我毕业了中给大家提到的刘某人程序员。
我们在群里等你!