JAVA面向对象高级
0 继承
继承是JAVA以后用的特别多也是特别重要的知识点,如果这个掌握不好的话,JAVA可以说是完了,所以一定要重视这个知识点。
格式就如下:
//定义父类
class 父类{
}
//子类用 extends 来继承父类
class 子类 extends 父类{
}
这里是写在了同一个程序里面,其实两个可以分开写,与前面写类一样的。
定义完成后,子类可以使用有父类的所有属性和方法,而且子类也可以定义其他的属性和方法。
例如:
class Person{
void say(){
System.out.println("我是人");
}
}
class Student extends Person{
}
public static void main(String[] args) {
Student s = new Studen();
s.say();
}
//结果为:我是人
看出来了,可以用子类直接调用父类的方法或者其他的成员等。
如果将上面的代码改一下:
class Student extends Person{
void say(){
System.out.println("我是人,并且我是学生");
}
}
再运行main函数结果就是----我是人,并且我是学生。这种将父类的方法重新写一遍,叫方法的重写
什么是方法的重写呢,就是将父类里面的方法重新写一遍;什么意思呢,就是你觉得父类的方法不好,子类里面不合适,想要重新写一个,这时候你不用重新去定义方法,只需要写一个与你想修改的方法同名的方法(这个方法一定要和父类里面的方法形式一模一样)然后内容的话就可以自己定义。
好总结一下重写的规则:
重写规则:
1、参数列表必须完全与被重写方法的相同;
2、返回类型必须与父类完全一致。
3、访问权限不能比父类中被重写的方法的访问权限更低,例如父类是一个public,子类就不能是 protected。
4、父类成员方法只能被他子类重写。
5、声明为static和private的方法不能被重写,但是能够再次声明。
重写和重载的区别:
1、发生的位置:
重载:一个类中
重写:子父类中
2、参数列表限制
重载:必须不同
重写必须相同
3、返回类型
重载:与返回值无关
重写:返回值类型必须一致
4、访问权限:
重载:与访问权限无关
重写:子的访问权限必须不能小于父类
5、异常处理(这个知识在后面):
重载:与异常无关
重写:异常范围可以更小,但是不能抛出新的异常
1 抽象类
概念:
抽象类必须使用abstract class声明 一个抽象类中可以没有抽象方法。抽象方法必须写在抽象类或者接口中。
格式如下:
abstract class 类名{// 抽象类
}
抽象方法
只声明而未实现的方法称为抽象方法(未实现指的是:没有“{}”方法体),抽象方法必须使用abstract关键字声明。
格式如下:
abstract class 类名{ // 抽象类
public abstract void 方法名() ; // 抽象方法,只声明而未实现
}
这里因为抽象类里面有抽象方法,所以必须要有子类它才有意义,抽象方法在子类里面可以根据用户的需要进行重写。
例如:
//抽象类
public abstract class Person {
//抽象方法
public abstract void say();
}
//护士子类
public class Nurse extends Person {
public void say() {
System.out.println("我是护士");
}
}
//学生子类
public class Student extends Person{
public void say() {
System.out.println("我是学生");
}
}
这个的作用就是,打个比方你在写项目,然后类里面的方法你还不知道写什么,或者说写的东西太多,需要分类写,这样你就可以写抽象方法要用的时候就去继承并重写。
常见问题
1、 抽象类能否使用final声明?
不能,因为final属修饰的类是不能有子类的 , 而抽象类必须有子类才有意义,所以不能。
2、 抽象类能否有构造方法?
能有构造方法,而且子类对象实例化的时候的流程与普通类的继承是一样的,都是要先调用父类中的构造方法(默 认是无参的),之后再调用子类自己的构造方法。
抽象类和普通类的区别
1、抽象类必须用public或protected修饰(如果为private修饰,那么子类则无法继承,也就无法实现其抽象方法)。默认缺省为public 。
2、抽象类不可以使用new关键字创建对象,但是在子类创建对象时,抽象父类也会被JVM实例化。
3、如果一个子类继承抽象类,那么必须实现其所有的抽象方法。如果有未实现的抽象方法,那么子类也必须定义为 abstract类。
2 接口
概念
如果一个类中的全部方法都是抽象方法,全部属性都是全局常量,那么此时就可以将这个类定义成一个接口。
定义格式:
interface 接口名称{
全局常量 ;
抽象方法 ;
}
面向接口编程思想
这个看一下,有个印象就行,以后工作了,这个会有大用的。
这种思想是接口是定义(规范,约束)与实现(名实分离的原则)的分离。
优点:
1、 降低程序的耦合性
2、 易于程序的扩展
3、 有利于程序的维护
接口的实现 implements
接口和继承类似,但又不完全一样,接口可以多实现
例如:
class 子类 implements 父接口1,父接口2...{
}
接口的继承
接口因为都是抽象部分,没有具体的实现,所以允许多继承。
例如:
interface C extends A,B{
}
来看个实例:
public interface Person {
void say();
}
public class Student implements Person {
public void say() {
System.out.println("老套路");
}
因为这些东西都比较抽象,例子看起来都比较幼稚;现在需要理解这些东西,好的例子都会在以后出现。
接口和抽象类的区别
1、抽象类要被子类继承,接口要被类实现。
2、接口只能声明抽象方法,抽象类中可以声明抽象方法,也可以写非抽象方法。
3、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
4、抽象类使用继承来使用, 无法多继承。 接口使用实现来使用, 可以多实现 。
5、抽象类中可以包含static方法 ,但是接口中不允许(静态方法不能被子类重写,因此接口中不能声明静态方法) 。
6、接口不能有构造方法,但是抽象类可以有。
3 多态
多态顾名思义就是对象的多种表现形式,(多种体现形态)。
还是拿之前继承的例子
class Person{
public void say() {
System.out.println("我是人");
}
}
class Student extends Person{
public void say(String text) {
//重写
System.out.println("我是学生");
}
}
class Nurse extends Person{
public void say(String text) {
//重写
System.out.println("我是护士");
}
}
在这里面Student和Nurse就都是Person的两种形态,也就是多态。
在多态中也有关系转换,如下:
· 向上转型:将子类实例变为父类实例 |- 格式:父类 父类对象 = 子类实例 ;
· 向下转型:将父类实例变为子类实例 |- 格式:子类 子类对象 = (子类)父类实例 ;
但是记住,两种多态之间不能转换。
接着上面的代码演示:
Person p = s; //假设Student s = new Student(); 写了
//这个可以
Student s = (Student)p; //假设 Person p = new Person(); 写了
//这个可以
Student s = (Student)n; //n是护士类
//这个就不行
就像上述一样,你可以把一个学生当人看,你也可以把一个人强行抓去当学生,因为“人”没有职业,可以“造化”,但是你不能把一个护士强行抓去当学生,别人护士上班上好好的,突然被抓去当学生,你说你懵不懵。4、
4 instanceof
这个提一下记住就可以了
作用就是判断某个对象是否是指定类的实例。
上例子
public class Demo2 {
public static void main(String[] args) {
Nurse n = new Nurse();
say(n);
Student s = new Student();
say(s);
}
public static void say(Person p) {
//如何判断传入的对象是此类型的那种形态(哪个子类的对象)
if(p instanceof Student) {
Student s = (Student)p;
s.say();
}else {
System.out.println("必须传入学生形态,才可以执行");
}
}
}
5 Object类
Object类是所有类的父类(基类),如果一个类没有明确的继承某一个具体的类,则将默认继承Object类。
例如我们定义一个类:
public class Person{
}
//其实它被使用时 是这样的:
public class Person extends Object{
}