JAVA学习记录第三阶段

一、继承

1.继承的概述

  • 继承是多态的前提,如果没有继承就没有多态;
  • 继承主要解决的问题:共性抽取;
  • 父类\基类\超类→子类\派生类;

PS:

  • 在父子类的继承关系中,如果成员变量重名,则创建子类对象时,访问有两种方式:
  1. 直接通过子类对象访问成员变量;
  2. 间接通过成员方法访问成员变量;
  • 子类中有的成员就用子类的,没有再向上去父类找;
  • 在内存空间层面上,方法区中,子类会生成一个指向父类的super_class;
  • 子类对象中包含一个完整的父类结构;

2.重名问题

2.1 局部变量与本类成员变量

  • 在含有局部变量的那个方法中,直接使用变量名则调用局部变量,使用this.变量名调用本类成员变量;

2.2 本类成员变量与父类成员变量

  • super.变量名则使用父类成员变量;

3.继承中方法的覆盖重写

  • 重写(Override):在继承关系当中,方法的名称一样,参数列表也一样,这一点和重载(Overload)不同,但子类中覆盖重写方法的返回值必须小于等于父类的返回值范围
  • 特点:子类对象优先用子类中覆盖重写的方法;
    子类方法的权限必须大于等于父类方法的权限修饰符:

public>protected>default(即留空不写)>private

  • @Override:写在覆盖重写的方法前,可以起到检测是否是有效的覆盖重写;

4. super关键字与this关键字

4.1 super关键字

super:调用父类构造方法;

  • 子类构造方法默认包含一个“super();”调用,所以一定是先调用的父类构造,再执行子类构造;
  • 子类构造可以通过super关键字来调用父类重载构造;
  • super的父类构造调用,必须是子类构造的第一个语句;
public class theFather {
    public theFather(int a) {
        System.out.println("父类无参构造");
    }
}
public class theSon extends theFather {
    public theSon() {
        super(2);
        System.out.println("子类无参构造");
    }
}

总结: 子类必须调用父类的构造方法,不写则赠送一个super(),写了则用写的那个,且写的时候只能写一次还必须放在子类构造的第一句;

super关键字的三种用法总结:

  1. super.变量名:在子类成员方法中访问父类的成员变量;
  2. super.方法名:在子类的成员方法中访问父类的成员方法;
  3. super():在子类构造方法中访问父类构造方法;

4.2 this关键字

作用:用来访问本类内容;

  1. 在本类的成员方法中访问本类的成员变量;
  2. 在本类的成员方法中访问本类的另一个成员方法;
  3. 在本类的构造方法中访问本类的另一个构造方法;
  • 和super()一样,this(参数)也必须是构造方法的第一个语句;
  • super()与this()不能同时使用,不难理解吧?

5、Java继承的三个特点

  1. Java语言是单继承的,一个类的直接父类只能有唯一一个;
  2. Java语言可以多级继承,java.lang.Object是最高级的父类;
  3. 一个父类可以被多个子类继承;

二、抽象

概念(我的见解):无法具体写出执行步骤、属性等?只是知道大致行为,类别;

1.抽象方法与抽象类的定义格式

  • 抽象方法:在修饰符与返回值类型之间加上abstract,并且去掉大括号,如:
public abstract void 方法名();
  • 抽象类:含有抽象方法的类,在class前写上abstract,如:
public abstract class 类名{
	public abstract void 方法名();
}

抽象类中也能定义普通方法;

2.抽象类与抽象方法的使用

  1. 不能直接new一个抽象对象;
  2. 必须用一个子类来继承抽象父类;
  3. 子类必须靠覆盖重写抽象父类当中的所有抽象方法;
  • 抽象类的覆盖重写:子类去掉抽象方法的abstract关键字并补上大括号;
  1. 创建子类对象;

3.抽象类的注意事项

1.抽象类不能直接创建对象,只能通过其子类来创建;
2.抽象类中可以有构造方法,在子类创建对象时,用来初始化父类成员;
3.抽象类中不一定包含抽象方法,但抽象方法必须要写在抽象类中;
4.抽象类的子类必须重写所有抽象方法:

在写子类时 “alt+回车” 即可自动弹出父类中需要覆盖重写的抽象方法;

三、接口

  • 接口就是一种公共的规范标准
    只要符合规范标准,就可以大家通用;

接口定义的格式:

public interface 接口名称{
	接口内容
}

PS:接口类定义时虽然把class换成了interface,但编译后的文件仍然是.class;

  • 如果是Java7,那么接口中可包含的内容有:
  1. 常量
  2. 抽象方法:接口当中的抽象方法修饰符必须是public abstract,也可以不写;
  • Java8:
  1. 默认方法
  2. 静态方法
  • Java9:
  1. 私有方法

3.1 接口的使用步骤

  1. 接口不能直接使用,必须有一个“实现类”来“实现”该接口;
public class 实现类名称 implements 接口名称{
	内容
}
  1. 接口的实现类必须覆盖重写(实现)接口中所有的抽象方法;

实现:去掉abstract关键字,加上方法体大括号;
若没有全部覆盖重写,则该实现类必须是一个抽象类;

在写实现类时 “alt+回车” 即可自动弹出接口类中需要覆盖重写的抽象方法;

3.创建实现类的对象,进行使用;

3.2 接口的默认方法

  • 定义格式:
public default 返回值类型 方法名称(参数列表){
	方法体
}
  • 作用:在接口类中添加的默认方法被实现类直接继承,而无需在实现类中覆盖重写, 你要覆盖重写也可以;

3.3 接口的静态方法

  • 定义格式
public static 返回值类型 方法名称(参数类型){
	方法体
}

PS:不能通过实现类的对象来调用接口当中的静态方法,应该直接通过接口名称来调用;

3.4 接口的常量定义和使用

  • 必须使用public static final(可省略)三个关键字进行修饰,从效果上看,这其实就是接口的常量
public static  final int 常量名 = 数值;//必须赋值

3.5 继承父类并继承多个接口

  1. 接口没有静态代码块或构造方法;
  2. 一个类的直接父类唯一,但一个类可以实现多个接口;
  3. 如果一个实现类的多个接口中有重名抽象方法,则只需要覆盖重写一次;
  4. 如果实现类没有重写所有的抽象方法,则实现类必须是一个抽象类;
  5. 如果实现类实现的多个接口中有重名的默认方法,则实现类必须将之覆盖重写;
  6. 一个类如果直接父类当中的方法和接口当中的默认方法产生冲突,则将优先使用父类的方法, 继承优先于实现接口;

3.6 接口之间的多继承

1.类与类之间是单继承的;
2.类与接口之间是多实现的;
3.接口与接口之间是多继承的;

PS:

  • 多个父接口当中的抽象方法重名,没关系;
  • 多个父接口当中的默认方法重名则需要在子接口中覆盖重写;

四、对象的多态性

  • 多态性的前提:extends继承或implements实现;
  • 多态是针对对象说的;

4.1 多态的格式与引用

代码当中体现多态性:父类引用指向子类对象

父类名称 对象名称 = new 子类名称();
或
接口名称 对象名称 = new 实现类名称();
  • 在使用时,优先调用new后面的东西(即),没有再向上寻找(即左边的父类或接口);

4.2 多态中成员变量的使用特点

*访问成员变量的两种方法:

  1. 直接通过对象名称访问成员变量,看等号的左边是谁就优先调用谁,没有则向上寻找
  2. 间接通过成员方法访问,则是看该方法属于谁,没有则向上寻找
    PS:编译看左,运行也看左;

4.3 多态中成员方法的使用特点

  • new的是谁,就优先用谁,没有则向上寻找;
    PS:编译看左(多态下,通过对象名调用父类中没有的子类方法会报错),运行看右;

4.4 对象的向上、向下转型

  • 对象的向上转型:其实就是多态写法:
父类名称 对象名=new 子类名称();

含义:右侧创建一个子类对象,把它当作父类来看待与使用;
PS:向上转型一定是安全的,因为它是从一个狭隘的范围跳向一个更宽泛的范围;

  • 对象的向下转型:就是我在4.3里写的“多态中通过对象名调用父类中没有的子类方法会报错”,所以需要有一个还原的动作;
    定义格式:
子类名称 对象名 = (子类名称)父类对象;//有点像强转???

注意那个对象名需要是一个新的名字;

  • 如何知道一个父类引用的对象本来是什么子类?
对象名 instanceof 类名称

它在判断完成后将返回一个boolean;

五、final关键字与四种权限修饰符

5.1 final的几种适用方法

  1. final修饰一个类
    格式:
public final class 类名称{
	内容
}

含义:该方法不能有子类,其中所有方法都不能覆盖重写,但可以有父类;

  1. fianl修饰一个方法
    格式:
修饰符 final 返回值类型 方法名称(参数列表){
	方法体
}

含义:该方法不能覆盖重写;

  1. final修饰一个局部变量
    格式:
final 数据类型 变量名 = 数据值;
或
final 数据类型 变量名;
变量名 = 数据值;

含义:一次赋值之后,该变量不能被更改;
对于引用类型,则表示变量名中存放的地址值不能改变;

  1. final修饰一个成员变量
  • 由于成员变量具有默认值,所以使用了final之后必须赋值;
  • 对于final的成员变量,要么使用直接赋值,要么使用构造方法赋值,二者选其一;
  • 必须保证类当中所有重载的构造方法都会最终对final的成员变量进行赋值;

5.2 final在局部内部类

  • 如果局部内部类希望访问其所在方法的局部变量,那么这个局部变量必须是有效final的,即不能二次赋值;

PS:从Java8开始,只要局部变量事实不变,那么final关键字可以省略;

  • 原因:
  1. new出来的对象在堆内存当中;
  2. 局部变量是跟着方法走的,在栈内存当中;
  3. 方法运行结束后立即出栈,局部变量立刻消失;
  4. 但是new出来的对象会在堆当中持续存在,直到垃圾回收消失;

5.3 权限修饰符

四种修饰符(从大到小)publicprotected(default)private
同一个类中yesyesyesyes
同一个包中yesyesyesno
不同包子类yesyesnono
不同包非子类yesnonono

六、内部类

  • 定义在 一个事物内部的类;

6.1 成员内部类:

  • 定义格式:
修饰符 class 外部类名称{
	修饰符 class 内部类名称{
	}
}

PS:内用外可,外用内不可;

  • 使用格式:
  1. 间接方式:在外部类的方法中使用内部类,然后main函数调用外部类方法;
  2. 直接使用:外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
  • 内部类的同名变量访问
    在内部类中,this.变量名表示该内部类下该变量名的成员变量,外部类名.this.变量名才是外部类的该变量名变量;

6.2 局部内部类

  • 定义在一个方法内部的类;
  • 定义格式:
修饰符 class 外部类名称{
	修饰符 返回值类型 外部方法名称(){
		class 局部内部类名称{
			内容
		}
	}
}
  • 只有当前方法能使用它,出了这个方法外面就不能用了;

6.3 类的权限修饰符使用规则

  1. 外部类:public\default;
  2. 成员内部类:public>protected>(default)>private;
  3. 局部内部类:什么都不能写,直接class;

6.4 匿名内部类

  • 如果接口的实现类父类的子类只需使用唯一一次,那么这种情况下就可以省略掉该类的定义,而改为使用匿名内部类;
  • 定义格式:
接口名称 对象名 = new 接口名称(){
	需要覆盖重写的方法
}	;//大括号内部是一个类,即匿名内部类;
  • 对格式“new 接口名称(){…}”进行解析:
  1. new表示创建对象的动作;
  2. 接口名称就是匿名内部类需要实现哪个接口;
  3. {…}是匿名内部类的内容
  • PS:
  1. 匿名内部类在创建对象的时候,只能使用唯一一次;
  2. 匿名的是内部类,而不是对象,若创建的是匿名对象,则也只能调用一个次方法;
    3.匿名的东西都只能用一次;
    4.匿名内部类和匿名对象不是同一回事!

6.5 类、接口作为成员变量

  • String就是一个类,好理解了吧?
  • 接口也差球不多;
  • 接口作为方法的参数与返回值也是可以的;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值