Java面向对象基础
1.final关键字
final是最终的意思,可以修饰类,方法,变量。
- 当修饰类时,这个类将不能再被继承;
- 当修饰方法时,方法将不能被重写,可以避免方法的含义被修改;早期java版本中对于final方法会内嵌调用,现在已不再使用这种方式;
- 当修饰变量时,这个变量是常量,值不能被修改;注意,分两种类型,基本类型在赋值后将不能再修改值,引用类型不可以改变其地址值,但具体的对象里的内容不受约束;
final修饰一个成员变量时,必须要显示初始化,而且只初始化一次,这里有两种初始化方式,一种是在变量声明的时候初始化;第二种方法是在声明变量的时候不赋初值,但是要在这个变量所在的类的所有的构造函数中对这个变量赋初值。
2.抽象类
在继承中,如果想要实现一样的方法声明,但在具体类中又有不同的方法体实现时,原来固定的直接给出方法声明与方法体的做法就不太合适,这时,我们在定义这种方法时,就可以定义为抽象方法,只需在方法声明最前面加abstract修饰,这样修饰的方法可以不用写方法体结构,而直接给出方法声明即可;
抽象类特点:
而一个类中如果有抽象方法,就必须定义为抽象类;且抽象类不能被创建对象实例化;
抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
抽象类的子类可以是一个抽象类或一个具体的子类,是具体类时必须要重写抽象类中的抽象方法;
抽象类的成员特点:
A:成员变量
有变量,有常量
B:构造方法
有构造方法
C:成员方法
有抽象,有非抽象
抽象类中的问题:
1.抽象类不能实例化,但它有构造方法,是用于子类访问父类数据的初始化;
2.一个类没有抽象方法但定义为抽象类时为了不让外界实例化对象,防止外界直接修改里面的成员;
3.abstract不能和哪些关键字共存
- final关键字,冲突,final修饰后的类和方法无法被继承和重写,无意义
- private 冲突,私有无法继承,无意义
- static 无意义,静态修饰后的方法可以直接通过类名调用,而访问一个无方法体的方法是没有意义的;
3.接口
Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
接口的特点:
A:接口用关键字interface修饰
interface 接口名 {}
B:类实现接口用implements修饰
class 类名 implements 接口名 {}
C:接口不能实例化
D:接口的实现类
a:是一个抽象类。
b:是一个具体类,这个类必须重写接口中的所有抽象方法。
接口没有构造方法,成员变量只能是常量,默认是public static final修饰的;对于成员方法默认是public abstract修饰;
接口与接口可以多继承,类与接口可以多实现;
为什么要用接口:
接口被用来描述一种抽象。
因为Java不像C++一样支持多继承,所以Java可以通过实现接口来弥补这个局限。
接口也被用来实现解耦。
为了程序的扩展性;
4.多态
java中的多态是指同一个对象在不同时刻体现出来的不同状态;
多态的前提:
A:有继承或者实现关系。
B:有方法重写。
C:有父类或者父接口引用指向子类对象。
多态的几种方式:
具体类多态:
class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
抽象类多态:
abstract class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
接口多态:
interface Fu {}
class Zi implements Fu {}
Fu f = new Zi();
多态中成员访问的特点:
- 访问成员变量时,访问的是父类的成员变量,即编译看左边,运行看左边;
- 访问构造方法,子类默认访问父类构造方法;
- 成员方法,访问的是子类的成员方法,因为有方法重写,需注意的是,使用多态访问成员方法时只能访问父类子类共有的成员方法,子类的私有成员方法不能访问;即编译看左边,运行看右边;
- 静态方法,编译看左边,运行看左边;
多态的好处:
1.提高代码维护性
2.提高代码扩展性
多态的弊端:
父类不能使用子类的特有功能;
多态中的转型:
class Fu {
public void show(){
System.out.println("Fu");
}
}
class Zi extends Fu {
public void show(){
System.out.println("Zi");
}
public void Zishow(){
System.out.println("Zi的特有功能");
}
}
class Test {
public static void main(String[] args){
//向上转型,子转父
Fu f = new Zi();
f.show(); //因为子类重写了show方法,会打印Zi
f.Zishow(); //报错,因为Zishow是Zi的特有功能,Fu无法访问
//向下转型,父转子
Zi z = (Zi)f;
z.Zishow(); //此时不再报错,因为已转为了子类实例对象
}
}