继承与多态
1.继承
基本语法:
public class 子类名称 extends 父类名称{…}
成员变量访问特点:
在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:
直接通过子类对象访问成员变量:
等号左边是谁,就优先用谁,没有则向上找
间接通过成员方法访问成员变量:
方法属于谁,就优先用谁,没有则向上找
成员方法访问特点:
创建的对象是谁,就优先用谁,如果没有则向上找
构造方法访问特点:
1.子类构造方法当中有一个默认隐含的super()调用,所以一定先调用父类构造,再执行子类构造
2.子类构造可以通过super关键字来调用父类构造。
3.super的父类构造调用,必须是子类构造的第一条语句。
super关键字用法:
1.在子类的成员方法中,访问父类的成员变量
2.在子类的成员方法中,访问父类的成员方法
3.在子类的构造方法中,访问父类的构造方法
public class son extends father{
public son(){
super();
System.out.println("子类构造方法");
}
public void method(){
System.out.println(super.num);
super.method();
}
}
this关键字用法:
1.在本类的成员方法中,访问本类的成员变量
2.在本类的成员方法中访问另一个成员方法
3.在本类的构造方法中访问另一个构造方法
JAVA继承特征:
1.JAVA是单继承
2.JAVA可以多级继承
2.抽象
抽象方法语法:
public abstract void 方法名();
抽象方法所在的类必须是抽象类
语法:
public abstract class 类名{}
public abstract class Person {
public abstract void method();
}
抽象类与抽象方法:
1.不能直接创建抽象类对象
2.必须用一个子类继承抽象父类
3.子类必须覆盖重写父类所有抽象方法
4.抽象类中可以有构造方法,是供子类创建对象时,初始化父类成员使用的
5.抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
public abstract class father {
public abstract void method();
}
public class son extends father{
@Override
public void method() {
System.out.println("这是一个子类方法");
}
}
3.接口
一种公共规范的标准,多个类的公共规范。
接口是一种引用数据类型,最重要的是抽象方法
语法:
public interface 接口名称{}
抽象方法:
public abstract 返回值类型 方法名称(参数列表);
注意:
1.接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
2.这两个关键字可以省略
使用:
1.接口不能直接使用,必须有一个实现类来实现该接口
public class 实现类名称 implements 接口名称{}
2.接口的实现类必须覆盖重写接口中所有的抽象方法
实现:去掉abstract关键字,加上方法体大括号
3.创建实现类的对象进行使用
public interface MyInterfaceAbstract {
public abstract void methodAbs(); //接口抽象方法的定义
}
public class MyInterfaceAbstractImpl implements MyInterfaceAbstract{
@Override
public void methodAbs() {
System.out.println("这是一个方法"); //重写接口的抽象方法
}
}
public class demo01Interface {
public static void main(String[] args) {
MyInterfaceAbstractImpl impl=new MyInterfaceAbstractImpl();
impl.methodAbs(); //创建对象实现抽象方法
}
}
默认方法
语法:
public default 返回值类型 方法名称(参数列表){}
1.接口的默认方法可以通过接口实现类对象直接调用
2.接口的默认方法可以被接口实现类进行覆盖重写
public interface MyInterfaceDefault {
public abstract void methodAbs();
// public abstract void methodAbs2(); //新增抽象方法
public default void methodDefault(){
System.out.println("这是新添加的默认方法");
}
}
public class MyInterfaceDefaultA implements MyInterfaceDefault{
@Override
public void methodAbs() {
System.out.println("实现抽象方法A");
}
}
public class MyInterfaceDefaultB implements MyInterfaceDefault{
@Override
public void methodAbs() {
System.out.println("实现抽象方法B");
}
@Override
public void methodDefault() {
System.out.println("这是B重写默认方法"); //覆盖重写
}
}
public class demo02Interface {
public static void main(String[] args) {
MyInterfaceDefaultA a=new MyInterfaceDefaultA();
a.methodAbs();
a.methodDefault(); //调用默认方法
MyInterfaceDefaultB b=new MyInterfaceDefaultB();
b.methodDefault(); //调用重写默认方法
}
}
静态方法
语法:
public static 返回值类型 方法名称(参数列表){}
注意事项:
1.不能通过接口实现类的对象来调用接口当中的静态方法
2.通过接口名称直接调用静态方法
public interface MyInterfaceStatic {
public static void methodStatic(){
System.out.println("这是一个静态方法");
}
}
public class demo03Interface {
public static void main(String[] args) {
MyInterfaceStatic.methodStatic();
}
}
私有方法
解决多个静态方法之间重复代码
普通私有方法:
private 返回值类型 方法名称(参数列表){}
静态私有方法:
private static 返回值类型 方法名称(参数列表){}
public interface MyInterfacePrivateA {
public default void MethodDefault1(){
System.out.println("这是默认方法1");
methodCommon();
}
public default void MethodDefault2(){
System.out.println("这是默认方法2");
methodCommon();
}
private void methodCommon(){
System.out.println("默认方法");
}
}
接口的常量
接口当中也可以定义成员变量,但是必须使用public static final三个关键字进行修饰
从效果上看,这其实就是接口的常量
语法:
public static final 数据类型 常量名称=数据值;
注意:
1.接口当中的常量可以省略public static final关键字
2.接口当中的常量必须赋值
3.接口中常量名称使用完全大写,用下划线分隔
使用:
接口名称.常量名称
public interface MyInterfaceConst {
public static final int NUM_My_Class=10;
}
多个接口
语法:
public class 类名称 implements 接口1,接口2{}
如果多个接口中存在重名的抽象方法,重写一次即可
如果实现类没有重写所有抽象方法,则实现类是一个抽象类
如果多个接口中存在重复的默认方法,那么实现类一定要对冲突的默认方法进行重写
一个类如果父类与接口当中的方法重名冲突,那么优先父类的方法
接口多继承
1.类与类之间单继承,直接父类只有一个
2.类与接口之间是多实现的,一个雷可以实现多个接口
3.接口与接口之间多继承
注意:
1.多个父接口当中的抽象方法如果重复,并无问题
2.多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,并且必须带default关键字
4.多态
语法:
父类名称 对象名=new 子类名称();
接口名称 对象名=new 实现类名称();
public class Father {
public void method(){
System.out.println("父类方法");
}
}
public class Son extends Father{
public void method(){
System.out.println("子类方法");
}
}
public class Demo01Multi {
public static void main(String[] args) {
Father obj=new Son();
obj.method(); //子类方法
}
}
访问成员变量的两种方式:
1.直接通过对象名访问成员变量:等号左边是谁优先用谁,没有则向上查找
2.间接通过成员方法访问成员变量:该方法属于谁优先用谁,没有则向上查找
成员方法访问的方式:
new的哪个类名,就有限用谁,没有则向上查找
成员变量:编译看左,运行看左
成员方法:编译看左,运行看右
如何才能知道一个父类的引用对象本来是什么子类?
语法:
对象 instanceof 类名称
这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例
5.final关键字
1.修饰类
当前这个类不能有任何子类
public final class 类名称(参数列表){}
2.修饰方法
当前这个方法不能被覆盖重写
public final 返回值 方法名称(参数列表){}
3.修饰局部变量
变量不可改变
final 变量类型 变量名称=值;
对于基本类型来说,不可变说的是变量当中的数据不可改变
对于引用类型来说,不可变说的是变量当中的地址值不可改变
4.修饰成员变量
对于成员变量来说,如果使用final关键字修饰,那么这个变量不可变
注意:
1.由于成员变量有默认值,所以用了final之后必须手动赋值
2.对于final的成员变量,要么直接赋值,要么通过构造方法赋值
6.权限修饰符
public | protected | default | private | |
同一个类 | yes | yes | yes | yes |
同一个包 | yes | yes | yes | no |
不同包子类 | yes | yes | no | no |
不同包非子类 | yes | no | no | no |
7.内部类
1.成员内部类
修饰符 class 类名称{
修饰符 class 内部类名称{}
}
注意:
内部类使用外部类随意访问;外用内一定要有内部类对象
public class Body {
public class Heart{
public void beat(){
System.out.println("内部类方法");
method(); //调用外部类方法
}
}
public void method(){
Heart heart=new Heart(); //调用内部类方法
System.out.println("外部类方法");
}
}
使用:
1.间接方式:在外部类的方法当中使用内部类,main只调用外部类方法
2.直接方式:
类名称 对象名=new 类名称();
外部类名称.内部类名称 对象名=new 外部类型名称
public class Body {
public class Heart{
public void beat(){
System.out.println("内部类方法");
method(); //调用外部类方法
}
}
public void method(){
Heart heart=new Heart(); //调用内部类方法
System.out.println("外部类方法");
}
}
public class demo01 {
public static void main(String[] args) {
Body body=new Body();
body.method();
Body.Heart heart=new Body().new Heart();
heart.beat();
}
}
同名变量访问:
外部类名称.this.成员变量
public class Outer {
int num=10;
public class Inner{
int num=20;
public void method(){
int num=30;
System.out.println(num); //30
System.out.println(this.num); //20
System.out.println(Outer.this.num); //10
}
}
}
2.局部内部类
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类
只有当前所属的方法才能使用它,出了这个方法外面就不能用了
语法:
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
}
}
}
public class Outer {
public void methodOuter(){
class Inner{ //局部内部类
int num=10;
public void methodInner(){
System.out.println(num);
}
}
Inner inner=new Inner();
inner.methodInner();
}
}
定义一个类的时候,权限修饰符规则:
1.外部类:public/default
2.成员内部类:public/protected/default/private
3.局部内部类:什么都不能写
匿名内部类:
接口名称 对象名=new 接口名称{
//覆盖重写所有抽象方法
}
public class DemoMain {
public static void main(String[] args) {
MyInterface obj=new MyInterface() {
@Override
public void method() {
System.out.println("匿名内部类实现方法");
}
};
obj.method();
new MyInterface(){
public void method(){
System.out.println("匿名内部类实现方法2");
}
}.method();
}
}
注意事项:
1.匿名内部类在创建对象的时候只能使用唯一一次,如果希望多次创建对象,而且类的内容一样的话,就必须使用单独定义的实现类了。
2.匿名对象,在调用方法的时候只能调用唯一一次,如果希望同一个对象调用多次方法,就必须给对象起个名字。
3.匿名内部类省略了实现类/子类名称,但是匿名对象是省略了对象名称