首页 > 编程语言 >学习笔记 - Java 面向对象_下

学习笔记 - Java 面向对象_下

时间:2023-08-26 17:12:25浏览次数:36  
标签:Java 对象 笔记 面向对象 枚举 实例 接口 方法 public

static 关键字

如果想让一个成员变量被类的所有实例所共享,就用 static 修饰即可,称为类变量(或类属性)

可修饰结构:属性、方法、代码块、内部类

对比静态变量和实例变量

  • 个数
    • 静态变量:只有一份,被多个对象共享;
    • 实例变量:每一个对象都保存着一份实例变量;
  • 内存位置
    • 静态变量:存放在堆空间;
    • 实例变量:存放在堆空间的对象实体中;
  • 加载时机
    • 静态变量:随着类的加载而加载;
    • 实例变量:随着对象的创建而加载;
  • 调用者
    • 静态变量:可以被类直接调用,也可以使用对象调用;
    • 实例变量:只能使用对象进行调用;
  • 判断是否可以调用(从生命周期的角度解释)
类变量 实例变量
对象
  • 消亡时机
    • 静态变量:随着类的卸载而消亡;
    • 实例变量:随着对象的消亡而消亡;

static 修饰方法

也可以称为类方法或静态方法。它随着类的加载而加载,可以通过 类.静态方法 的方式直接调用。

静态方法可以调用其它静态的结构,不可以调用非静态的结构(实例对象、方法、构造器),同时静态方法中无法使用 this 和 super 关键字。

单例设计模式

设计模式概述

设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。经典的设计模式共有23种

image

单例模式概述

采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。

实现单例模式

饿汉式

  1. 私有化类的构造器;
  2. 在类内部创建当前类的静态实例属性;
  3. 使用静态的 get() 方法获取当前类的实例。
class Bank{
    private Bank(){}
    
    private static Bank instance = new Bank();
    
    public static Bank getInstance(){
        return instance;
    }
}

懒汉式

  1. 私有化类的构造器;
  2. 在类内部声明当前类的静态实例属性;
  3. 在静态的 get() 方法内创建当前类的实例,使用 get() 方法时即可获取当前类的实例。
class Bank{
    private Bank(){}
    
    private static Bank instance = null;
    
    public static Bank getInstance(){
        if(instance == null){
            instance = new Bank();
        }
        return instance;
    }
}

对比两种方式

  • 特点
    • 饿汉式:立即加载,随着类的加载,实例就创建了;
    • 懒汉式:延迟加载,在需要使用的时候进行创建
  • 优点
    • 饿汉式:写法简单,由于在内存种较早加载,使用更方便、更快,是线程安全的;
    • 懒汉式:在需要的时候进行创建,节省内存空间;
  • 缺点
    • 饿汉式:内存中占用时间较长;
    • 懒汉式:线程不安全;

main 方法

public static void main(String args[]){}

理解1:看作是一个普通的静态方法(可以通过控制台调用);

理解2:看作是程序的入口,格式是固定的。

代码块

代码块用来初始化类或对象的信息,由一对 {} 构成。其可以使用的修饰符只有 static ,故可以分为静态代码块和非静态代码块。其使用规范与方法大致相同。

  • 静态代码块

    • 随着类的加载而执行且只会执行一次,用来初始化类的信息。
  • 非静态代码块

    • 随着对象的创建而执行且每当实例化一个对象时就会执行一次,用来初始化对象的信息。

补充知识

可以给类的非静态属性赋值的方式及其执行顺序为:

  1. 默认初始化
  2. 显式初始化 或 代码块中初始化
  3. 构造器初始化
  4. 创建对象后,通过 对象.属性对象.方法 进行赋值。

final 关键字

final 可以理解为最终的,可以用来修饰类、方法和变量。

  • final 修饰类:表示该类不能被继承;
  • final 修饰方法:表示此方法不能被重写;
  • final 修饰变量:表示该值不能被更改,相当于一个常量。
    • 对于成员变量,只能通过显式赋值、代码块赋值以及构造器赋值。与 static 搭配时表示该成员变量为全局常量

抽象(abstract)

子类拥有共同特征,但在父类中却无法给出具体的实现,所以父类在声明这些方法时就只有方法签名,没有方法体。没有方法体的方法称为抽象方法,而包含抽象方法的类必须是抽象类。

abstract 修饰类

  • abstract 关键字修饰的类为抽象类,抽象类不能被实例化;

  • 抽象类中是包含构造器的,子类对象实例化时会调用该构造器;

  • 抽象类中可以没有抽象方法。

abstract 修饰方法

  • abstract 关键字修饰的方法为抽象方法,抽象方法只有方法声明,没有方法体;
  • 子类必须重写父类中的所有抽象方法后才可以实例化,否则该子类仍是一个抽象类。

补充

  • abstract 不能修饰属性、构造器、代码块等;

  • abstract 不能用来修饰私有方法、静态方法、final 的方法和类。

接口(interface)

接口是规范,定义的是一组规则。继承是 is-a 的关系,而接口是 has-a (能不能)的关系。

接口结构

  • 可以声明:
    • 属性:必须使用 public static final 修饰(可以省略);
    • 方法:jdk8之前只能声明抽象方法,用 public abstract 修饰(可以省略);jdk8可以声明静态方法、默认方法;jdk9可以声明私有方法。
  • 不可以声明:构造器、代码块等。

接口的实现

接口和类之间为实现关系,格式为:class A extends SuperA implements B, C (一个类可以实现多个接口)。

类针对于接口的多实现,一定程度上弥补了类单继承的局限性。

实现类必须将接口中所有的抽象方法都实现才可以实例化,否则该类要声明为抽象类。

接口之间可以多继承,最终的实现类需要实现所有接口的方法;

接口的多态性

格式:接口名 变量名 = new 实现类对象

public class USBTest {

    public static void main(String[] args) {
    
        Computer computer = new Computer();
        
        // 1.创建接口实现类的对象
        Printer printer = new Printer();
        computer.transferData(printer);


        // 2.创建接口实现类的匿名对象
        System.out.println("\n*****************");
        computer.transferData(new Camera());


        // 3.创建接口实现类的匿名对象
        System.out.println("\n*****************");
        USB usb1 = new USB() {
            @Override
            public void start() {
                System.out.println("U盘开始工作...");
            }

            @Override
            public void stop() {
                System.out.println("U盘停止工作...");
            }
        };
        computer.transferData(usb1);


        // 4.创建接口匿名实现类的匿名对象
        System.out.println("\n*****************");
        computer.transferData(new USB() {
            @Override
            public void start() {
                System.out.println("扫描仪开始工作...");
            }

            @Override
            public void stop() {
                System.out.println("扫描仪开始工作...");
            }
        });
    }
}


class Computer{

    public void transferData(USB usb){
        System.out.println("设备连接成功...");
        usb.start();
        System.out.println("数据传输...");
        usb.stop();
    }
}


class Printer implements USB{

    @Override
    public void start() {
        System.out.println("打印机开始工作...");
    }

    @Override
    public void stop() {
        System.out.println("打印机停止工作...");
    }
}


class Camera implements USB{

    @Override
    public void start() {
        System.out.println("照相机开始工作...");
    }

    @Override
    public void stop() {
        System.out.println("照相机停止工作...");
    }
}


interface USB{
    
    void start();
    void stop();
}

区分抽象类和接口

  • 共性:
    • 都可以声明抽象方法;
    • 都不能实例化
  • 不同:
    • 抽象类一定有构造器而接口没有;
    • 类和接口的本质不同导致的不同。

image

内部类(InnerClass)

概述

将一个类 A 定义到另一个类 B 里边,则称 A 为内部类(InnerClass),B 为外部类(OuterClass)。

具体来说,当一个事物 A 的内部,还有一个部分需要一个完整的结构 B 进行描述,而这个内部的完整的结构 B 又只为外部事物 A 提供服务,不在其它地方单独使用,那么整个内部的完整结构 B 最好使用内部类。

内部类的分类

  • 成员内部类:直接声明在外部类的里面
    • 使用 static 修饰的:静态的成员内部类
    • 不使用 static 修饰的:非静态的成员内部类
  • 局部内部类:声明在方法内、构造器内、代码块内的内部类
    • 匿名的局部内部类
    • 非匿名的局部内部类

成员内部类

从类的角度来看:

  • 内部可以声明属性、方法、构造器、代码块、内部类等结构;
  • 此内部类可以声明父类,可以实现接口;
  • 可以使用 final 、abstract 关键字修饰

从外部类成员的角度来看:

  • 在内部可以调用外部类的结构,例如属性、方法等;
  • 所有的权限修饰符都可以使用(一个 .java 文件中只有一个类可以用 public 修饰,其它类只能用缺省修饰);
  • 可以使用 static 修饰

创建成员内部类的实例:

// Dog 类为 Person 类的静态内部类,Bird 类为非静态内部类

//1.创建 Person 的静态的成员内部类的实例
Person.Dog dog = new Person.Dog();
dog.eat();

//2.创建 Person 的非静态的成员内部类的实例
Person p1 = new Person();
Person.Bird bird = p1.new Bird();
bird.eat();

在内部类中调用外部类的同名属性和方法时,通过 外部类.this.方法\属性 的方式进行调用。

局部内部类

开发中的场景:

public Comparable getInstance(){
    
    //方式1:提供了接口实现类的匿名对象
    class MyComparable implements Comparable{
        
        @Override
        public int compareTo(Object o){
            return 0;
        }
    }
    return new MyComparable();
    
    //方式2:提供了接口的匿名实现类的对象
    Comparable c = new Comparable(){
        @Override
        public int compareTo(Object o){
            return 0;
        }
    };
    return c;
    
    //方式3:提供了接口的匿名实现类的匿名对象
    return new Comparable(){
        @Override
        public int compareTo(Object o){
            return 0;
        }
    };
    
}

通过编译文件理解内部类

image

枚举类(Enum)

概述

枚举类本质上也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。

在开发中,如果针对于某个类的实例对象是确定个数的,则推荐将子类声明为枚举类。如果枚举类的实例只有一个,可以看作是单例的实现方式。

使用方法

在 jdk5 之后可以通过 enum 关键字来声明枚举类。其默认父类是 java.lang.Enum ,不允许再显式的声明其父类。

enum Season{

    // 1.必须在枚举类的开头声明多个对象,对象之间用 "," 隔开
    SPRING("春天", "春暖花开"),
    SUMMER("夏天", "夏日炎炎"),
    AUTUMN("秋天", "秋高气爽"),
    WINTER("冬天", "白雪皑皑")
    ;

    // 2.声明当前类的对象的实例变量,使用 private final 修饰
    private final String SEASON_NAME; // 季节名称
    private final String SEASON_DESC; // 季节描述

    // 3.私有化类的构造器
    Season(String SEASON_NAME, String SEASON_DESC) {
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }

    // 4.提供实例变量的 get 方法
    public String getSEASON_NAME() {
        return SEASON_NAME;
    }

    public String getSEASON_DESC() {
        return SEASON_DESC;
    }
}

Enum 类中常用方法

String toString ( ):默认返回的是常量名 (对象名),可以继续手动重写该方法!

static 枚举类型[ ] values ( ):返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值,是一个静态方法。

static 枚举类型 valueOf (String name):可以把一个字符串转为对应的枚举类对象(可以理解为在枚举类对象中查找名称为该字符串的)。要求字符串必须是枚举类对象的"名字"。如不存在该名字的,会有运行时异常(IllegalArgumentException)。

String name ( ):得到当前枚举常量的名称。建议优先使用 toString ( ) 。

int ordinal ( ):返回当前枚举常量的次序号,默认从 0 开始。

枚举类实现接口

情况1:枚举类实现接口,在枚举类中重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是同一个方法。

情况2:在枚举类的每一个对象重写接口中的方法。当通过不同的枚举类对象调用此方法时,执行的是不同的方法。

注解(Annotation)

概述

注解可以像修饰符一样被使用,可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明,还可以添加一些参数值,这些信息被保存在 Annotation 的 “name=value” 对中。

注解可以在类编译、运行时进行加载,体现不同的功能。

元注解

对现有注解进行解释说明的注解。

  1. @Target:用于描述注解的使用范围,可以通过枚举类型 ElementType 的 10 个常量对象来指定;
  2. @Retention:用于描述注解的声明周期,可以通过枚举类型 RetentionPolicy 的 3 个常量对象来指定;
  3. @Documented:表明这个注解应该被 javadoc 工具记录;
  4. @Inherited:允许子类继承父类中的注解。

Junit 单元测试

概述

黑盒测试:不需要写代码,输入值看程序是否能够输出期望的值。

白盒测试:需要写代码,关注程序具体的执行流程。

使用方法

导入 Junit 包后在待测试的方法上添加 @Test 注解后可以单独允许方法。

包装类

概述

为了使基本数据类型的变量具备引用数据类型变量的相关特征(例如:封装性、继承性、多态性),Java 针对基本数据类型定义了相应的引用类型:包装类(封装类)。

基本数据类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
boolean Boolean
char Character

包装类和基本数据类型间的转换

  • (装箱)基本数据类型 --> 包装类:

    • 使用包装类的构造器(jdk9之后被弃用)

    • 使用包装类的 valueOf() 方法(推荐)

  • (拆箱)包装类 --> 基本数据类型:

    • 调用包装类的xxxValue()方法

jdk5之后可以自动装箱和自动拆箱,例如:

// 自动装箱
Integer i1 = 10;

// 自动拆箱
int i2 = i1;

String 类型与包装类或基本数据类型间的转换

  • 基本数据类型、包装类 --> String 类型:
    • 调用 String 的重载的静态方法 valueOf(xxx xx)
    • 使用基本数据类型 + '' 的方式即可
  • String 类型 --> 基本数据类型、包装类:
    • 调用包装类的静态方法:parseXxx( )

image

标签:Java,对象,笔记,面向对象,枚举,实例,接口,方法,public
From: https://www.cnblogs.com/KoiC/p/17659109.html

相关文章

  • Nacos笔记(六):Nacos应用 - 注册中心、配置中心
    Nacos官网:https://nacos.io/zh-cn/index.html。Nacos注册中心/配置中心搭建官方文档地址:https://nacos.io/zh-cn/docs/v2/ecology/use-nacos-with-spring-cloud.html。1、注册中心Nacos注册中心原理图:  1.1、项目搭建创建新项目,项目结构如下:  父......
  • 社团算法学习笔记
    社团算法学习笔记:https://gaowenxin95.github.io/le_graph/社团社区发现算法学习笔记.html......
  • JAVA 集合
    Java集合体系Java集合框架图Java集合主要分为两大类:实现了Collection接口的单列集合:实现了Map接口的双列集合:集合框架体系序号接口描述1Collection接口Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素,Java不提供直接继......
  • Java日志框架的依赖设置备查(SLF4J, Log4j, Logback)
    前言最近在看代码的过程中,发现身边的许多人在使用Java日志框架时,对于应该引入何种依赖不甚了解,搜索网络上的文章,常常也是互不一致。这篇文章可以看着是Java日志框架的入门使用和实践建议,重点介绍不同组合方式下的依赖设置及其背后的逻辑,一方面给自己备查,另外也希望对小伙伴们......
  • 缩点+割点学习笔记
    缩点传送门根据题意:允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。所以我们可以考虑将可以相互到达的若干个点缩成一个点,以方便计算。下面讲如何实现:考虑\(dfs\),并且对点记录如下信息\(dfn\)(该点被遍历到的时间节点,即该点是第几个被遍历到的),\(low\)(可以追溯到......
  • 多阶前缀和学习笔记
    例题传送门:P4062[Code+#1]Yazid的新生舞会简要题意:给定一串序列\(A_1,A_2,...,A_n\),求有多少个子区间\([l,r]\)满足子区间内众数的个数大于\(\frac{r-l+1}{2}\)思考若数\(w\)是众数的方案数:新建一个序列\(B\),令\(B_i=[A_i=w]\),考虑前缀和\(S_i=\sum\limits_{k=1}^iB_i=S_{i-1......
  • 失配树学习笔记
    传送门考虑把原字符串先\(kmp\)一遍,求出以\(i\)结尾的前缀的最长\(border\),根据\(border\)的\(border\)还是\(border\)这个定理,我们在寻找前缀\(p\)和前缀\(q\)的最长公共\(border\)时,我们可以考虑运用这个定理,一直往前跳,找到最先一样的\(border\),这就是最长公共\(bordedr\),至于......
  • Dirichlet 前缀和学习笔记
    传送门求\(b_k=\sum\limits_{i|k}{a_i}\)考虑\(i=p_1^k,j=p_1^{k+1}\),若我们已经求出了\(b_i\),则易知\(b_j=b_i+a_j\)然后根据上面的方法,考虑对于所有的\(k=p_1^{k1}p_2^{k2}...p_l^{kl}\),若\(j=p_2^{k2}...p_l^{kl}\),我们已经求出所有的\(c_k=a_j+a_{p1\timesj}+a_{p1^2\time......
  • 回文自动机(PAM)学习笔记
    传送门我认为理解回文自动机需要图,以\(abbaabba\)为例,它的回文树是这样的:令树上的每一个点为一个回文串,其中,\(1\)为根的树中的点回文串长度为奇数,且最中间的那个字母就是\(1\)连向其他点的的边的字母,而\(0\)为根的树中的点回文串长度为偶数。举点例子吧:点\(2\)的回文串为\(a\)......
  • c语言笔记6
    c语言笔记6(结构体,共用体,枚举,文件操作,makefile)1.结构体1.1结构体的概念结构体也是构造类型之一,由至少一个基本数据类型或构造类型组成的一种数据结构(集合),这种数据结构称之为结构体1.2结构体的定义使用结构体之前,先定义结构体,然后使用这个结构体时作为一种数据类型(......