Java超全面笔记(四)--- 面向对象(下)

static关键字:

  1. 可用来修饰:属性、方法、代码块、内部类【都是随着类的加载而加载】
  2. 使用static修饰的属性:静态变量(类变量)
  1. 属性按是否使用static修饰,分为静态属性VS非静态属性(实例变量)

实例变量:创建了类的多个对象,每个对象独立拥有一套非静态属性,修改其中一个对象的非静态属性,不影响其他对象

静态变量:多个对象共享同一个静态变量,通过一个对象修改,其他对象调用此静态变量时是修改过的

  1. 其他说明
  • 静态变量随着类的加载而加载【可通过类.静态变量的方式进行调用】
  • 静态变量的加载早于对象的创建
  • 由于类只会加载一次,所以静态变量在内存中也只会存在一份,存在方法去的静态域中
  1. 使用static修饰的方法:静态方法
  1. 可通过类.方法名调用
  2. 静态方法中,只能调用静态的方法或属性

非静态方法中,静态/非静态的方法或属性都可以

  1. 静态方法内,this,super关键字都不能用
  2. 开发中,如何确定一个属性是否要声明为static的?

属性可以被多个对象共享,不会随着对象的不同而不同

  1. 开发中,如何确定一个方法是否要声明为static的?

操作静态属性的方法通常为static

工具类中的方法,习惯声明为static。如:Math, Arrays

单例设计模式

采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例

实现:饿汉式VS懒汉式

饿汉式

class Bank{
    private Bank(){

    }

    private static Bank instance = new Bank();

    public static Bank getInstance(){
        return instance;
    }
}

懒汉式

class Order{
    private Order(){

    }

    private static Order instance = null;

    public static Order getInstance(){
        if (instance == null)
            instance = new Order();
        return instance;
    }

}

区分:

饿汉式:坏处:对象加载时间过长,一开始就要加载

              好处:线程安全

懒汉式:好处:延迟对象的创建,要用的时候才创建

              坏处:目前的写法线程并不安全

代码块

  1. 作用:用来初始化类、对象
  2. 代码块如果有修饰,只能用static
  3. 分类:静态代码块VS非静态代码块
  4. 静态代码块

>内部可写输出语句

>随着类的加载而运行

>作用:初始化类的信息(对静态属性进行重新赋值)

>若一个类中定义了多个代码块,按声明顺序先后执行

>静态代码块的执行优先于非静态代码块

>静态代码块只能调用静态属性、方法,不能调用非静态的结构

  1. 非静态代码块

>内部可写输出语句

>随着对象的创建而运行【每创建一个对象就执行一次】

>作用:可以在创建对象时,对对象的属性等进行初始化

>非静态代码块可以调用静态属性、方法以及非静态属性、方法

赋值先后顺序

  1. 默认初始化
  2. 显示初始化
  3. 构造器中初始化
  4. 创建对象后,通过“对象.属性”或“对象.方法”赋值
  5. 在代码块中赋值

优先级:1->2/5->3->4

final关键字

  1. 可用来修饰类、方法、变量
  2. 修饰一个类:此类不能被其他类继承,如String类、System类
  3. 修饰一个方法:此方法不能被重写
  4. 修饰变量:此时该变量变成一个常量,不能再进行赋值
  1. final修饰属性,可考虑的赋值位置有:显式初始化,代码块中,构造器初始化
  2. 局部变量:尤其是使用final修饰形参时,此形参是一个常量,调用此方法时,给常量形参赋一个值,之后只能在此方法体中使用该形参,不能重新赋值

static final 可修饰属性、方法

属性:全局常量

abstract关键字

可修饰类、方法

修饰类:抽象类

       此类不能实例化

       抽象类中一定有构造器,便于子类对象实例化时调用(涉及子类对象实例化全过程)

       开发中,都会提供抽象类的子类,让子类对象实例化完成相关操作

修饰方法:抽象方法

       只有方法的声明,没有方法体【public abstract void go();】

       包含抽象方法的类一定是抽象类

       若子类重写了父类中的所有抽象方法,此子类才能实例化

       若没有全部重写,则子类也是一个抽象类

【注意点】

  1. 不能修饰属性、构造器
  2. 不能修饰私有方法、静态方法、final方法(不能被重写)、final的类(不能继承)

抽象类的匿名子类

method1(new student()); //匿名对象

Worker worker = new Worker();
method1(worker); //非匿名类的非匿名对象

method1(new Worker());  //非匿名类的匿名对象


//创建了一个匿名子类的非匿名对象
Person p = new Person(){
    @Override
    public void eat() {
        super.eat();
    }
};//方法体中把抽象方法全部重写/方法体中把抽象方法全部重写

//创建了一个匿名类的匿名对象
method1(new Person() {
    @Override
    public void eat() {
        super.eat();
    }
});

接口

  1. 使用interface定义
  2. 接口和类是并列的两个结构
  3. 如何定义接口:定义接口中的成员
  1. JDK7及以前,只能定义全局常量和抽象方法

> 全局常量:public static final的【可以省略不写,默认就是这样】

> 抽象方法:public abstract【可以省略不写,默认就是这样】

  1. JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
  1. 接口中不能定义构造器,即不可实例化
  2. 开发中,通过类实现(implement)接口的功能
    1. 如果实现类覆盖了接口中的所有抽象方法,则可以实例化
    2. 如果实现类没有覆盖接口中的所有抽象方法,则是抽象类,
  3. Java类可以实现多个接口

格式:class A extends B implements C,D,E

接口的使用:

接口的具体使用体现了多态性(可被多个类实现)

接口实际上可以看作是一种规范

public class USBTest {
    public static void main(String[] args) {
        Computer c = new Computer();
        Flash flash = new Flash();

        c.transferData(flash);
    }
}

interface USB{
    void start();

    void stop();
}


class Computer{
    public void transferData(USB usb){
        usb.start();
        usb.stop();
    }
}


class Flash implements USB{
    @Override
    public void start() {
        System.out.println("开始");
    }

    @Override
    public void stop() {
        System.out.println("停止");
    }
}

【形参类型为接口的类型时,在实际调用时代入的是实现了该接口的类的对象】

//1.接口的非匿名实现类的非匿名对象
Flash flash = new Flash();
c.transferData(flash);
//2.接口的非匿名实现类的匿名对象
c.transferData(new Flash());
//3.接口的匿名实现类的非匿名对象
USB u = new USB() {
    @Override
    public void start() {
        System.out.println("s");
    }

    @Override
    public void stop() {
        System.out.println("b");
    }
};

//4.接口的匿名实现类的匿名对象
c.transferData(new USB() {
    @Override
    public void start() {
        System.out.println("s");
    }

    @Override
    public void stop() {
        System.out.println("b");
    }
});

代理模式

public class NetWorkTest {
    public static void main(String[] args) {
        Server server = new Server();
        ProxyServer proxyServer = new ProxyServer(server);
        proxyServer.browse();
    }
}

interface NetWork{
    void browse();
}



//被代理类
class Server implements NetWork{
    @Override
    public void browse() {
        System.out.println("访问网络");
    }
}


//代理类
class ProxyServer implements NetWork{
    private NetWork work;
    public ProxyServer(NetWork work){
        this.work = work;
    }


    @Override
    public void browse() {
        check();
        work.browse();

    }


    public void check(){
        System.out.println("before work");
    }
}

没有显式地用Server调用browse()方法,而是通过ProxyServer调用了Server中的browse()方法。【因为ProxyServer中可能还会在调用一些其他的方法,可以用这个类代理实现Server中要实现的方法】

应用场景

工厂模式

实现创建者和调用者的分离

JDK8中的接口:

除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法

  1. 接口中定义的静态方法,只能通过接口进行调用【接口.方法】
  2. 通过实现类的对象,可以调用接口中的默认方法(如果实现类重写了接口中的默认方法,调用时仍然是调用重写的方法)
  3. 如果子类(或实现类)继承的父类和实现的接口声明了同名同参的方法,那么在子类没有重写该方法的情况下,默认调用的是父类中的方法à类优先原则
  4. 如果实现类实现了多个接口,而这些接口中定义了同名同参的方法,则在子类没有重写该方法的情况下,会报错à接口冲突【所以必须要重写该方法】
  5. public void myMethod(){
        //调用自己定义的重写方法
        method3();
        //调用父类中声明的
        super.method3();
        //调用接口中定义的默认方法
        CompareA.super.method3();
    }
    

内部类

  1. 将一个类A声明在另一个类B中,则A为内部类,B为外部类
  2. 分类:成员内部类VS局部内部类(方法内、代码块内、构造器内)
  3. 成员内部类:

一方面,作为外部类的成员

  • 调用外部类的结构【调用外部类的方法时:外部类名.this.方法名】
  • 可以被static修饰
  • 可被四种不同的权限修饰符修饰

另一方面,作为一个类

  • 类内可以定义属性、方法、构造器等
  • 可以被final修饰,表示不能被继承;不用final就可以被继承
  • 可以被abstract修饰     
  1. 1)如何实例化成员内部类的对象

2)如何在成员内部类中区分外部类的结构

3)开发中局部内部类的使用

//创建静态内部类
Person.Dog dog = new Person.Dog();
//创建非静态内部类
Person p = new Person();
Person.Bird bird = p.new Bird();

在局部内部类的方法中,如果如果调用局部内部类所声明的方法中的局部变量,要求此局部变量声明为final的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值