面向对象进阶

01.static静态变量

  • static表示静态, 是Java中的一个修饰符, 可以修饰成员方法, 成员变量

  • 被static修饰的成员变量, 叫做静态变量

  1. 特点: 被该类所有对象共享; 不属于对象,属于类; 随着类的加载而加载, 优于对象存在

  2. 调用方式: 类名调用(推荐) , 对象名调用

02.static静态方法和工具类

  • 被static修饰的成员方法,叫做静态方法

  1. 特点:多用在测试类和工具类中; Javabean类中很少会用

  2. 调用方式: 类名调用(推荐); 对象名调用

  • Javabean类: 用来描述一类事物的类。比如,Student,Teacher,Dog,Cat等
    测试类: 用来检查其他类是否书写正确,带有main方法的类,是程序的入口
    工具类: 不是用来描述一类事物的,而是帮我们做一些事情的类
    1. 类名见名知意 2. 私有化构造方法 3.方法定义为静态

public class ArrUtil {
private Arrutil(){}
public static int getMax(...){...}
public static int getMin(...){...}
public static int getsum(...){...}
public static int getAvg(...){...}
}

03.static的注意事项

  • 静态方法只能访问静态变量和静态方法

  • 非静态方法可以访问静态变量或者静态方法,也可以访问非静态的成员变量和非静态的成员方法

  • 静态方法中是没有this关键字

总结: 静态方法中,只能访问静态。 非静态方法可以访问所有。 静态方法中没有this关键字

04.继承的概述

继承:

  • Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起继承关系。

    public class student extends Person {}
  • Student称为子类(派生类),Person称为父类(基类或超类)。

使用继承的好处:

  • 可以把多个子类中重复的代码抽取到父类中了,提高代码的复用性

  • 子类可以在父类的基础上,增加其他的功能,使子类更强大

什么时候用继承?

当类与类之间,存在相同(共性)的内容,并满足子类是父类中的一种,就可以考虑使用继承,来优化代码

05.继承的特点和继承体系的设计

继承的特点:

Java只支持单继承, 不支持多继承, 但支持多层继承 (每一个类都直接或间接的继承于object, 子类只能访问父亲中非私有的成员)

单继承:一个子类只能继承一个父类

不支持多继承:子类不能同时继承多个父亲

多层继承:子类A继承父类B, 父类B可以继承父类C

06.子类能继承父类中的哪些内容

  • 结论:

构造方法非私有 不能private 不能
成员变量非私有 能private 能 (不能直接使用)
成员方法非私有(虚方法表) 能private(不是虚方法表) 不能
  • 成员方法是否可以被继承: (只有父类中的虚方法才能被子类继承)

A类 方法A继承B类 方法B继承C类 方法C
虚方法表 在 B的基础上再添加自己类中的虚方法虚方法表 在 C的基础上再添加自己类中的虚方法虚方法表 非private 非static 非final

07.继承中成员变量和成员方法的访问特点

继承中:成员变量的访问特点:

public class Fu {
     String name = "Fu" ;
}
public class zi extends Fu{
     String name = "Zi";
     public void ziShow(){
        String name = "ziShow";
        system.out.println(name);
     }
}

就近原则: 首先在局部位置找, 如果没有就在本类成员位置找,还没有就到父类的成员位置找,逐级往上

public class Fu {
     String name = "Fu";
}
public class Zi extends Fu{
     String name = "zi";
     public void ziShow(){
        String name = "ziShow" ;ziShow
        System.out.println(name);            //ziShow 从局部位置开始往上找
        System.out.println(this.name) ;      //zi  从本类成员位置开始往上找
        System.out.println(super.name);      //Fu   从父类成员位置开始往上找
     }
}

继承中: 成员方法的访问特点

  1. 直接调用满足就近原则 : 谁离我近,我就用谁

  2. super调用,直接访问父类

方法的重写 (本质: 覆盖虚方法表中的方法)

当父类的方法不能满足子类现在的需求时,需要进行方法重写

  • 书写格式 在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法。

  • @override重写注解 1.@Override是放在重写后的方法上,校验子类重写时语法是否正确。

    2.加上注解后如果有红色波浪线,表示语法错误。

    3.建议重写方法都加@Override注解,代码安全,优雅

  • 注意事项:

    1. 重写方法的名称、形参列表必须与父类中的一致。

    2. 子类重写父类方法时,访问权限子类必须大于等于父类(暂时了解∶空着不写<protected < public)

    3. 子类重写父类方法时,返回值类型子类必须小于等于父类

    4. 建议:重写的方法尽量和父类保持一致。

    5. 只有能被添加到虚方法表中的方法才能被重写

08.继承中的构造方法和this、super关键字

继承中:构造方法的访问特点

  • 父类中的构造方法不会被子类继承

  • 子类中所有的构造方法默认先访问父类中的无参构造,再执行自己

(子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。

子类初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化。

子类构造方法的第一行语句默认都是: super(),不写也存在,且必须在第一行。

如果想调用父类有参构造,必须手动写super进行调用。)

this、super使用总结

  • this: 理解为一个变量,表示当前方法调用者的地址值;

  • super: 代表父类存储空间

关键字访问成员变量访问成员方法访问构造方法
thisthis.成员变量this.成员方法(...)this(...)
访问本类成员变量访问本类成员方法访问本类构造方法
supersuper.成员变量super.成员方法(...)per(...)
访问父类成员变量访问父类成员方法访问父类构造方法

09.认识多态

  • 什么是多态?

同类型的对象,表现出的不同形态.

  • 多态的表现形式

父类类型 对象名称 = 子类对象;

  • 多态的前提

  1. 有继承/实现关系;

  2. 有父类引用指向子类对象

  3. 有方法重写

  • 多态的好处?

使用父类型作为参数,可以接收所有子类对象,体现多态的拓展性与便利

010.多态中调用成员的特点

  • 成员变量调用:编译看左边,运行也看左边

  • 成员方法调用:编译看左边,运行看右边(先检查左边的父类中有没有这个方法,如果没有直接报错)

011.多态的优势和弊端

  • 优势:

  1. 在多态形式下,右边对象可以实现解耦合,便于拓展和维护

  2. 定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的拓展性与便利

  • 弊端:

不能使用子类的特有功能

  • 引用数据类型的类型转换,有几种方式?

自动类型转换、强制类型转换

Person p = new student ();   (自动)
Student s = (Student)p;      (强制)
  • 强制类型转换能解决什么问题?

    1. 可以转换成真正的子类类型,从而调用子类独有功能。

    2. 转换类型与真实对象类型不一致会报错

    3. 转换的时候用instanceof关键字进行判断

/*if(a instanceof Dog){                        (instance左边是变量名,右边是类名,判断左边是否属于右边,属于true,不属于fa
Dog d = (Dog) a;d .lookHome( );
}else if(a instanceof Cat){
cat c = (cat) a;
c.catchMouse( ) ;}else{
system.out.println("没有这个类型,无法转换");}*/
​
//jdk14 新特性
//先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d
//如果不是,则不强转,结果直接是false
if(a instanceof Dog d)i
d .lookHome( );
}else if(a instanceof Cat c){
c.catchMouse( );
}else{
system. out.println("没有这个类型,无法转换");
}

012.包和final

  • 什么是包?

包就是文件夹。用来管理各种不同功能的Java类,方便后期代码维护。

包名的规则:公司域名反写+包的作用,需要全部英文小写,见名知意。com.itheima. domain

package com.itheima. domain;
public class Student {
私有化成员变量构造方法
成员方法
}
​
com.itheima. domain.Student   全类名/全限定名
  • 使用其他类的规则

  1. 使用同一个包中的类时,不需要导包。

  2. 使用java.lang包中的类时,不需要导包。

  3. 其他情况都需要导包 (选中 alt + 回车 自动导包)

  4. 如果同时使用两个包中的同名类,需要用全类名。

  • final

方法: 表明该方法是最终方法,不能被重写

类: 表明该类是最终类,不能被继承

变量: 叫做常量,只能被赋值一次

  • 常量

实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性。

常量的命名规范:

  1. 单个单词:全部大写

  2. 多个单词:全部大写,单词之间用下划线隔开

细节:

final修饰的变量是基本类型:那么变量存储的数据值不能发生改变。

final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,对象内部的可以改变

013.权限修饰符和代码块

权限修饰符

  • 是用来控制一个成员能够被访问的范围的

  • 可以修饰成员变量,方法,构造方法,内部类

权限修饰符的分类:

有四种作用范围由小到大(private<空着不写(缺省/默认)<protected<public)

修饰符同一个类中同一个包中其他类不同包下的子类不同包下的无关类
private
空着不写
protected
public

权限修饰符的使用规则:

实际开发中,一般只用private和public (成员变量私有, 方法公开)

特例 : 如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有。

代码块(局部代码块、构造代码块、静态代码块)

  • 局部代码块:

public class Test {
    public static void main(String[] args) {
    /*      {
            int a = 10;
            system.out.println(a);         (单独的一个括号就叫代码块) (局部代码块)
        }                                */
    }
}
  • 构造代码块:

1.写在成员位置的代码块 2.作用:可以把多个构造方法中重复的代码抽取出来 3.执行时机:我们在创建本类对象的时候会先执行构造代码块再执行构造方法

public class student {
private string name;private int age;public student() {
system.out.println("开始创建对象了");}
pub1ic student(string name, int age) f
system.out.println("开始创建对象了");this.name = name;
this.age = age;
}
}
public class student
private string name;private int age;
/*{
system.out.println("开始创建对象了");        (构造代码块)(多个构造方法中重复的代码)
} */
public student() {
}
public student(String name,int age) {
this.name = name;
this.age = age;
}
}
  • 静态代码块

格式:staticl{}

特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次

使用场景:在类加载的时候,做一些数据初始化的时候使用。

014.抽象类和抽象方法

  • 抽象方法: 将共性的行为((方法)抽取到父类之后。由于每一个子类执行的内容是不一样,所以,在父类中不能确定具体的方法体。该方法就可以定义为抽象方法。

  • 抽象类: 如果一个类中存在抽象方法,那么该类就必须声明为抽象类

  • 抽象类和抽象方法的定义格式:

抽象方法的定义格式:
public abstract 返回值类型 方法名(参数列表);
​
抽象类的定义格式:
public abstract class类名{}
​
(报错时点红色波浪线 按Alt + 回车 点make ... abstract 即生成抽象类和抽象方法, 点Implement methods 即重写父类中所有的抽象方法)
  • 抽象类和抽象方法的注意事项

    1. 抽象类不能实例化(不能创建对象)

    2. 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类

    3. 可以有构造方法

    4. 抽象类的子类, 要么重写抽象类中的所有抽象方法, 要么是抽象类

  • 抽象类的作用是什么样的? 抽取共性时,无法确定方法体,就把方法定义为抽象的。强制让子类按照某种格式重写。 抽象方法所在的类,必须是抽象类。

015.接口

  • 接口:就是一种规则.是对行为的抽象

  • 接口的定义和使用:

  1. 接口用关键字interface来定义

    public interface接口名{}

  2. 接口不能实例化

  3. 接口和类之间是实现关系,通过implements关键字表示

    public class 类名 implements 接口名{}

  4. 接口的子类(实现类)

要么重写接口中的所有抽象方法 要么是抽象类

注意1: 接口和类的实现关系,可以单实现,也可以多实现。

public class 类名 implements 接口名1,接口名2{}

注意2: 实现类还可以在继承一个类的同时实现多个接口。

public class 类名 extends 父类 implements 接口名1,接口名2{}

016.接口的细节:成员特点和接口的各种关系

接口中成员的特点:

  1. 成员变量

只能是常量 默认修饰符: public static final

  1. 构造方法 没有

  2. 成员方法 只能是抽象方法 默认修饰符: public abstract

    JDK7以前: 接口中只能定义抽象方法。

    JDK8的新特性:接口中可以定义有方法体的方法。(默认、静态)

    JDK9的新特性:接口中可以定义私有方法。(普通的私有方法、静态的私有方法)

接口和类之间的关系

  • 类和类的关系

继承关系,只能单继承,不能多继承,但是可以多层继承

  • 类和接口的关系

实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口

  • 接口和接口的关系

继承关系,可以单继承,也可以多继承

如果实现类实现了最下面的子接口,那么就需要重写所有的抽象方法

接口中新增方法,接口应用和适配器设计模式

JDK8以后接口中新增的方法:

  • 允许在接口中定义默认方法,需要使用关键字default修饰

作用:解决接口升级的问题

  • 接口中默认方法的定义格式:

格式:public default 返回值类型方法名 (参数列表) { }

范例: public default void show(){ }

  • 接口中默认方法的注意事项:

  1. 默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写的时候去掉default关键

  2. public可以省略,default不能省略

  3. 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写

  • 允许在接口中定义定义静态方法,需要用static修饰

  • 接口中静态方法的定义格式:

格式: public static返回值类型方法名(参数列表){ }

范例: public static void show(){ }

  • 接口中静态方法的注意事项:

  1. 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用

  2. public可以省略,static不能省略

  • 接口的应用:

  1. 接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这个类实现对应的接口就可以了。

  2. 当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态。

  • 适配器模式:

  1. 设计模式(Design pattern) (设计模式就是各种套路) :

是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

  1. 适配器设计模式: 解决接口与接口实现类之间的矛盾问题

  • 当一个接口中抽象方法过多,但是我只要使用其中一部分的时候,就可以适配器设计模式

  • 书写步骤: 编写中间类XXXAdapter,实现对应的接口

    对接口中的抽象方法进行空实现

    让真正的实现类继承中间类,并重写需要用的方法

    为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰

017.初识内部类

  • 什么是内部类?

在一个类的里面, 再定义一个类 (B类表示的事物是A类的一部分,且B单独存在没有意义)

  • 类的五大成员:

属性、方法、构造方法、代码块、内部类

public class Outer{       (外部类)
    public class Inner{   (内部类)
        
    }
}

内部类表示的事物是外部类的一部分 内部类单独出现没有任何意义

  • 内部类的访问特点 :

  1. 内部类可以直接访问外部类的成员,包括私有

  2. 外部类要访问内部类的成员,必须创建对象

018.成员内部类

内部类的分类

成员内部类、静态内部类、局部内部类 (前三个了解) 匿名内部类(掌握)

  • 成员内部类: (写在成员位置的,属于外部类的成员)

    public class car {                  (外部类)
        string carName;                 
        int carAge;
        int carcolor;
        public class Engine{            (成员内部类)
            string engineName;
            int engineAge;
        }
    }

编写成员内部类的注意点: 1.成员内部类可以被一些修饰符所修饰,比如: private,默认,protected,public,static等

2.在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量。

获取员内部类对象的两种方式: 方式一: 当成员内部类被private修饰时, 外部类编写方法,对外提供内部类对象

方式二:当成员内部类被非私有修饰时, 直接创建 格式:外部类名.内部类名对象名=外部类对象.内部类对象; 范例: outer.Inner oi = new outer( ).new Inner( );

  • 外部类成员变量和内部类成员变量重名时,在内部类如何访问?

    Outer.this 获取外部类对象的地址值

  • 静态内部类

    (静态内部类也是成员内部类中的一种,只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建外部类对象)

public class car {                  (外部类)
    string carName;                 
    int carAge;
    int carcolor;
    static class Engine{            (静态内部类)
        string engineName;
        int engineAge;
    }
}

创建静态内部类对象的格式: 外部类名.内部类名对象名= new 外部类名.内部类名();

调用非静态方法的格式: 先创建对象,用对象调用

调用静态方法的格式: 外部类名.内部类名.方法名();

  • 局部内部类

  1. 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。

  2. 外界是无法直接使用,需要在方法内部创建对象并使用。

  3. 该类可以直接访问外部类的成员,也可以访问方法内的局部变量。

  • 匿名内部类

    匿名内部类本质上就是隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置

    格式:
        new 类名或者接口名(){
            重写方法;
        };
    (继承\实现 、 方法重写  、 创建对象)
    ​
    举例:
        new Inner(){
            public void show(){         
            }
        };
    从new到分号,即一整个算是一个类的子类对象或者接口的实现类对象;  从第一个大括号到最后的分号才是一个没有名字的类

    使用场景: 当方法的参数是接口或者类时, 以接口为例,可以传递这个接口的实现类对象, 如果实现类只要使用一次,就可以用匿名内部类简化代码。

  • 以前的写法:
    Dog d = new Dog();
    method( d);
    //如果Dog类我只要用一次,那么还需要单独定义一个类太麻烦了。
    method (
            new Animal() {
                @override
                public void eat( ) {
                system.out.print1n("狗吃骨头");
                }
            }
    );

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值