继承:
1、继承是多态的前提,没有继承就没有多态。
2、继承主要解决的问题是:共性抽取。
3、继承的特点:
- 子类可以拥有父类可继承的内容。
- 子类可以拥有自己专有的内容。
继承关系中,“子类就是一个父类”。也就是说子类可以被当做父类看待。
4、定义父类的格式:(一个普通的类定义)
public class 父类名称{
//
}
定义子类的格式:
public claass 子类名称 extends 父类名称{
//
}
5、父子继承关系中,成员变量重名访问规则:
成员变量,属于谁,就优先使用谁的变量,没有则往上找。
父,子,还有子局部变量重名访问:
局部变量 直接写成员变量名
本类的成员变量 this.成员变量名
父类的成员变量 super.成员变量名
6、成员方法访问:
- 成中方法重名访问规则:创建的对象是谁的,就优先使用谁的,没有向上找。
- 方法的重写,覆盖:
在继承关系中方法的名称一样,参数列表也一样。注意:重写发生在继承关系中。
特点:
创建是子类对象,优先使用子类方法。实际与重名方法访问规则一致。
@Override:注解,起安全检测作用。写在方法前面,用来检测是不是有效的正确覆盖重写。
覆盖重写的子类方法的返回值必须小于等于父类的返回值范围。
子类方法的权限修饰符必须大于等于父类的权限修饰符。
注:权限修饰符大小:public > protected > (default,就是:什么都不写) > private
什么时候用覆盖重写呢?对于已经使用的类,尽量不要进行修改,可定义一个新的派生类,重复利用其中共性内容,对于已经有的功能要想改的话就用覆盖重写功能。override.
- 继承中构造方法访问特点:
子类必须调用父类构造方法,不写则赠送super();写了调用指定的super调用。super()只能有一个,还必须是第一个。super()和this()二者不能同时使用。
- 继承特征:
java语言是单继承的。一个类的直接父类只能有唯一一个。
java语言可以多级继承。
一个父类可以拥有很多子类。
抽象类:是由抽象方法得出的,不能确定具体方法(也就是没有方法)称为抽象方法
抽象方法:加上abstract关键字,然后去掉大括号,直接分号结束。
抽象类:抽象方法所在的类。并且必须是抽象类,class前加上abstract即可。
- 如何使用抽象类和抽象方法?1、不能直接创建抽象类对象,必须使用一个子类来继承抽象类。2、子类必须覆盖重写(实现)抽象父类当中所有的抽象方法。也就是去掉抽象方法的abstract关键字,然后补上方法体大括号。3、创建子类对象进行使用。
接口:公共的规范标准,代码接口就是多个类的公共规范,是一种引用数据类型。最重要的内容就是其中的:抽象方法。
- 格式:
public interface 接口名称{
//接口内容
}
- 接口包含内容:
1、常量 2、抽象方法 3、默认方法 4、静态方法 5、私有方法
注意事项:
抽象方法:
接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
两个关键字修饰符,可以选择性的省略。
接口:
1、接口是没有静态代码块或者构造方法
2、一个类的直接父类是唯一的,但一个实现类可以同时实现多个接口
3、一个实现类多个接口中有重名的抽象类,只覆盖重写一次就可以
4、如果实现类没有覆盖重写所有的抽象类,那这个类必须也是一个抽象类
5、接口类中存在重名的默认方法,实现类一定要对冲突的默认方法进行覆盖重写。
6、一个类如果直接父类当中的默认方法,和接口中的默认方法产生冲突,优先使用父类方法,在java中继承是优先于接口的。
接口的多继承:
多个父接口当中的抽象方法如果重复,没关系
多个父接口中默认方法如果重复,那么子接口必须进行默认方法的覆盖重写【而且带着default关键字】
- 接口使用步骤:
1、接口对象不能直接创建,必须有一个实现类,来“实现”接口。
格式:
public class 实现类名称 implements 接口名称{
//
}
2、接口中的实现类必须覆盖重写(实现)接口中所有的抽象方法
3、创建实现类对象,进行使用。
- 接口中的默认方法:格式:
public default 返回值类型 方法名称(参数列表){
//方法体
}
可以解决接口升级问题?不强制覆盖重写。也就是当接口新加方法时,通过默认方法,可以不用修改实现类的方法(因为实现类要覆盖重写接口类所有的抽象方法)
1、接口的默认方法,可以通过接口实现类对象直接调用
2、也可以被接口实现类进行覆盖重写
- 接口中的静态方法,带static
格式:
public static 返回值类型 方法名称(参数列表){
//方法体
}
注意事项:
1、不能实现类对象来调用接口中的静态方法。
2、而是通过接口名称直接调用静态方法
- 接口中的私有方法:从java9+开始,允许使用,解决接口中方法间重复代码而不在实现类中可见,并且只有接口自己才能调用,不能被实现类或别人使用。
普通私有方法:解决多个默认方法之间重复代码问题
格式:
private 返回值类型 方法名称(参数列表){
}
静态私有方法:解决多个静态方法之间重复代码问题
private static 返回值类型 方法名称(参数列表){
}
- 接口中的成员变量,其实是常量
接口中常量:使用public static final三个关键字进行修饰,可以省略。一旦使用final关键字进行修饰,说明不可改变。
格式:
public static final 数据类型 常量名称 = 数据值;//必须进行赋值,不写会报错。
多态:父类引用指向子类对象
- 格式:
父类名称 对象名 = new 子类名称();
或者:
接口名称 对象名 = new 实现类名称();
- 成员变量访问规则
编译看左边,运行还是看左边
- 方法访问规则
编译看左边,运行看右边
- 使用场景:
无论 new 对象怎么变,左边都是同一个。
- 对象上下转型
对象的向上转型:多态写法 父类名称 对象名 = new 子类名称();//创建一个子类对象,把它当作父类来看待使用
注意事项:向上转型一定是安全的,小范围转向了大范围。所以是安全的
向下转型:【还原的动作】
格式:子类名称 对象名 = (子类名称) 父类对象;
- 如何知道一个父类引用的对象,本来是什么子类?
格式:对象 instanceof 类名称
这将会得到一个boolean值结果,也就是判断前面的对象能不能当作后面类型的实例。
final关键字:最终的,不可改变的
常见四种用法:
1、可以用来修饰一个类
格式:
public final class 类名称{
//
}//含义:当前这个类不能任何子类
2、修饰一个方法:不能被覆盖重写
格式:
修饰符 final 返回值类型 方法名称(参数列表)
注意:
对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。
3、修饰一个成员变量:修饰后,变量不可变
由于成员变量具有默认值,所以用了final后,必须手动赋值,不会再给默认值了。
对于final的成员变量要么直接赋值,要么使用构造方法赋值,两者只能选其一
必须保证类中所有重载的构造方法(无参与有参的构造),都最终会对final的成员变量进行赋值。
4、修饰一个局部变量:修饰后变量就不能更改,只要保证有唯一一次赋值即可。
对于基本类型来说,不可以指的是变量中的数据不可改变。
对于引用类型来说,不可变说指变量当中的地址值不可改变。
权限修饰符:
java中有四种权限修饰符;
public > protected > (default) > private
同一个类(我自己): yes yes yes yes
同一个包(我邻居): yes yes yes no
不同包子类(继承)(我儿子): yes yes no no
不同包非子类(陌生人): yes no no no
内部类:一个事物包含另一个事件,那么就是一个类包含另一个类,另一个类就是内部类
1、成员内部类
- 定义格式:
修饰符 class 类名称{//外部类名称
修饰符 class 类名称{//内部类名称
//.....
}
//.....
}
注:内用外,随意访问,外用内,需要内部对象。
- 如何使用成员内部类?
间接方式:在外部类的方法中,使用内部类,然后main只是调用外部类的方法。
直接方式:外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
- 内部类同名变量访问?
外部类名称.this.外部类成员变量名
2、局部内部类:(包含匿名内部类):如果一个类定义在一个方法内部的,那么这就是一个局部内部类。
- 格式:
修饰符 class 外部类名称 {
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部类名称 {
//..
}
}
}
- 使用:
想方设法通过调用所属的局部方法。因为只有局部的方法才能使用局部内部类
权限修饰符:
外部类: pulic /(default)
成员内部类:public /protected/(default)/private
局部内部类:什么都不写。
注意:
局部内部类,如果希望访问所在方法的局部变量,那么这个变量必须【是有效final的】
从java8开始,只要局部变量事实不变,那么final关键字可以省略。
为什么?
1、New出来的对象在堆内存中,也就是局部类是需要new的,然后放到堆中
2、局部变量是跟着方法走的,在栈中。
3、方法运行结束后,立刻出栈,局部变量就会消失
4、但new出来 的对象会在堆中持续存在,直到垃圾回收,所以要是还希望使用方法的局部变量,只能复制一份放到堆中。
- 匿名内部类,最重要的同部类,用的也是最多的。
匿名内部类场景?
如果接口的实现类(或者父类的子类)只需要使用唯一的一次,那么这种情况下就可省略掉该类的定义,而改为使用【匿名内部类】。
格式:
接口名称 对象名 = new 接口名称(){
//覆盖重写所在的抽象方法。
};//分号注意不要省
注意事项:
匿名内部类与匿名对象不是一回事
匿名内部类省略了【实现类或子类名称】,匿名对象是省略了【对象名称】。