第四章:面向对象编程(高级)

第八章:面向对象编程(高级)

1.static修饰成员变量与方法

1.static:静态的

2.Static 用来修饰的结构:属性、方法;代码块、内部类;

3.static修饰属性:

3.1复习:变量的分类

方式1:按照数据类型:基本数据类型、引用数据类型

方式2:按照类中声明的位置:

成员变量:按照是否使用static修饰进行分类

使用static:静态变量、类变量

不使用:非静态变量、实例变量

局部变量:方法内、方法形参、构造器内、构造器参数、代码块内

3.2对比静态变量与实力变量:

① 个数

  • 静态变量:在内存空间中只有一份,被类的多个对象所共享
  • 实例变量:类的每一个实例都保存着一份实例变量

② 内存位置

  • 静态变量:jd6及之前,存放在方法区。jdk7及以后:存放在堆空间
  • 实例变量:堆空间的对象实体中

③ 加载时机

  • 静态变量:随着类的加载而加载,由于类只会加载一次,所以静态变量也只有一份
  • 实例变量:随着对象的创建而加载。每个对象拥有一份实例变量

④ 调用者

  • 静态变量:可以被类直接调用,也可以使用对象调用
  • 实例变量:只能使用对象调用

⑤ 判断是否可以调用 ---> 从生命周期的角度解释

 

类变量

实例变量

类

yes

no

对象

yes

yes

⑥ 消亡时机

  • 静态变量:随着类的消亡消亡
  • 实例变量:随着对象的消亡消亡

4.static修饰方法:(类方法、静态方法)

  • 随着类的加载而加载
  • 可以通过“类.静态方法”的方式直接调用
  • 静态方法内可以调用静态属性或方法,不可以调用非静态结构
 

类方法

实例方法

类

yes

no

对象

yes

yes

  • 在类的非静态方法中,可以调用当前类的静态结构或非静态结构
  • static中不能用this

5.开发中,什么时候需要将属性声明为静态的?

  • 判断当前类中的多个实例是否能共享此成员变量,且值相同
  • 开发中,把一些常量声明为静态:Math类中的PI

什么时候需要将方法声明为静态的?

  • 方法内操作的变量如果都是静态的
  • 开发中,将工具类中的方法,声明为静态。比如:Arrays类,Math类

2.单例设计模式

何为单例设计模式:

在整个软件爱你中,对于某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

实现思路:

  • 饿汉式
  • 懒汉式

特点:

  • 饿汉式:“立即加载”,随着类的加载,实例直接创建
  • 懒汉式:“延迟加载”,在需要使用的时候进行创建

优缺点:

  • 饿汉式:(优点)写法简单;内存中加载早,使用方便、快;线程安全;(缺点)内存中占用时间长
  • 饿汉式:(优点) 在需要的时候进行创建,节省内存空间(缺点)线程不安全

3.类的成员之四:代码块

1.代码块的作用:

  • 初始化类或对象的信息(即初始化类或对象的成员变量)

2.代码块的修饰符:

  • 只能使用static进行修饰

3.代码块的分类:

静态代码块:使用static修饰

非静态代码块:没有使用

4.具体使用

静态代码块:

  • 随着类的加载而执行
  • 由于类的加载只会执行一次,所以静态代码块的执行也只会执行一次
  • 作用:用来初始化类的信息
  • 内部可以声明变量、调用属性或者方法、编写输出语句
  • 静态代码块的执行要先于非静态
  • 多个静态代码块,按照顺序执行
  • 内部只能调用静态结构(即静态的属性、方法)

非静态代码块:

  • 随着对象的创建而执行
  • 每创建一个当前类的一个实例就会执行一次
  • 作用:用来初始化对象的信息
  • 内部可以声明变量、调用属性或者方法、编写输出语句
  • 多个非静态代码块,按照顺序执行

4.总结:属性赋值过程

1.可以给类的非静态的属性赋值的位置有:

①默认初始化

②显示初始化

③构造器中初始化

⑤代码块中初始化

④有了对象以后,通过"对象.属性"或者“对象.方法”进行f赋值

2.执行的先后顺序

①-②/⑤-③-④

3.给实例变量赋值的位置很多,开发中如何选?

  • 显示赋值:比较适合每个对象的属性值相同
  • 构造器赋值:每个对象属性值不同

5.final关键字的使用

1.关键字的理解:最终的

2.可以用来修饰的结构:类、方法、变量

3.具体说明:

3.1.final修饰类:表示此类不能被继承

比如String、StringBuffer、StringBuilder

3.2.final修饰方法:表示此方法不能被重写

Object里面的getClass(),

3.3.final修饰变量:可以是成员变量,也可以是局部变量。此时变量变成了常量,一但赋值不可更改

3.3.1.修饰成员变量:

显式赋值

代码块中赋值

构造器中赋值

3.3.2修饰局部变量:

方法内声明的局部变量(调用前一定要赋值)

方法的形参:在调用此方法时,给形参赋值

4.final与static搭配,修饰成员变量,此成员变量称为:全局常量。

比如Math中的PI

6.抽象类与抽象方法

举例1:

几何图形要计算面积啥的,但是每个图形的面积计算公式不一样,此时适合声明抽象方法(子类继承抽象父类,里面的抽象方法必须全部重写)

Plain Text
class abstract GeometricObject{
//求面积
public abstract void mianji();
public abstract void zhouchang()'
}
class Circle extends GeometricObject{
public void mianji(){

}
public void zhouchang(){

}
}

1.概念:抽象的

2.可以用来修饰:类、方法

3.具体的使用:

3.1修饰类:

  • 称为抽象类
  • 抽象类不能实例化
  • 抽象类中包含构造器,子类独享实例化时候会调用父类的构造器
  • 抽象类可以没有抽象方法,但是反过来不行

3.2修饰方法:

  • 成为抽象方法
  • 抽象方法只有声明,没有方法体
  • 功能确定,只是不知道如何具体实现

4.abstract不能使用场景:

4.1 不能修饰哪些结构?

  • 属性、构造器、代码块

4.2 abstract不能跟哪些关键字共用?(自洽)

不能修饰私有方法、静态方法、final的方法、final的类

7.接口interface

1.理解:接口的本质是契约、标准、规范,就像我们的法律一样,制定好后大家都要遵守

2.关键字:interface

3.接口内部结构的说明

可以声明:

属性:必须使用public staitc final修饰

方法:jdk8之前:声明抽象方法,修饰为public abstract

jdk8:声明静态方法、默认方法

jdk9:声明私有方法

不可以声明:构造器、代码块等

4.接口跟类的关系: 实现关系

5.格式: class A extends Super A implements B,C{}

A相较于SuperA来说,是子类

相较于B、C来说,是实现类

6.满足此关系后,说明:

  • 类可以实现多个接口
  • 类正对于接口的多实现,一定程度上就弥补了类的单继承的局限性。
  • 类必须将实现的接口中的所有的抽象方法都重写,方可实例化。否则就是个抽象类

7.接口与接口的关系:继承关系,且可以多继承

8.接口的多态性:接口名 变量名 = new 实现类对象

面试题:区分抽象类和接口

共性:都可以声明抽象方法

都不能实例化

不同:抽象类一定有构造器,接口没有

类与类之间是继承关系,类与接口是实现关系

8.类的成员之五:内部类(不是特别重要)

1.什么是内部类?

讲一个类A定义在类B里面。A:内部类 B:外部类

2.为什么需要内部类?

当一个事物A内部,有一个部分需要一个完整的结构B进行描述,这个B只为外部事物A提供服务,那么这个B最好用内部类

3.内部类使用举例

Thread类内部声明了State类,表示线程的生命周期

HashMap类中声明了Node类,表示封装的key和value

4.内部类的分类

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

5.要讲的知识

  • 成员内部类的理解
  • 如何创建成员内部的实例
  • 如何在成员内部类中调用外部类
  • 局部内部类的基本使用

6.成员内部类的理解

  • 从类的角度看:
  • 内部可以声明属性、方法、构造器、代码块、内部类
  • 可以声明父类,实现接口
  • 可以使用final修饰
  • 可以使用abstract修饰
  • 从外部类的成员角度看
  • 在内部可以调用外部类的结构:属性、方法等
  • 除了使用public、缺省修饰之外,还可以用private和protected
  • 可以使用static修饰

9.枚举类

1.定义:

本质上也是一种类,但是类的对象是有限的固定的几个,不能让用户随意创建

2.例子:

星期、性别、月份、季节等等

3.开发中的建议:

开发中,如果针对于某个类,其实例是确定个数的。推荐声明为枚举类

如果枚举类的实例只有一个,可以看做是单例的实现方式

4.如何定义枚举类

JDK5.0之前

Java
//声明当前类的对象的实例变量
private final String seasonName;
private final String seasonDesc;
//1.私有化类的构造器
private Season(String seasonName, String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}

//get

public String getSeasonName() {
return seasonName;
}

public String getSeasonDesc() {
return seasonDesc;
}

//创建当前类的实例,需要使用public static final修饰
public static final Season spring = new Season("Spring", "春暖花开");
public static final Season summer = new Season("Summer","夏日炎炎");
public static final Season autumn = new Season("Autumn","秋高气爽");
public static final Season Winter = new Season("Winter","白雪皑皑");

JDK5.0之后

TypeScript
//JDk5.0+使用enum关键字定义枚举类
enum Season1 {
//1.必须在枚举类开头声明多个对象,对象之间使用逗号隔开
spring("Spring", "春暖花开"),
summer("Summer","夏日炎炎"),
autumn("Autumn","秋高气爽"),
Winter("Winter","白雪皑皑");
//2声明当前类的对象的实例变量
private final String seasonName;
private final String seasonDesc;
//3.私有化类的构造器
private Season1(String seasonName, String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}

//4.get

public String getSeasonName() {
return seasonName;
}

public String getSeasonDesc() {
return seasonDesc;
}

@Override
public String toString() {
return "Season1{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}

5.Enum常见用法

使用enum关键字定义的枚举类,默认父类是java.lang.Enum类

String toString():默认返回对象名字

String name():和toString一样

Int ordinal():返回当前枚举的次序号,默认从零开始

Static 枚举类型.values():返回对象数组

Static 枚举类型 valueOf(String name):把一个字符串转化为对应的枚举类对象,有点类似查找

6.枚举类实现接口的操作

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

Plain Text
@Override
public void show() {
System.out.println("这是一个季节");
}

情况2:让枚举类的每一个的对象重写抽象方法,执行后实现不同的方法

TypeScript
spring("Spring", "春暖花开") {
@Override
public void show() {
System.out.println("这是一个季节");
}
},
summer("Summer", "夏日炎炎"){
@Override
public void show() {
System.out.println("这是一个季节");
}
},
autumn("Autumn", "秋高气爽"){
@Override
public void show() {
System.out.println("这是一个季节");
}
},
Winter("Winter", "白雪皑皑"){
@Override
public void show() {
System.out.println("这是一个季节");
}
};

10.注解(Annotation)

Annotation的理解:

注解是从JDK5开始引入的,以@注解名在代码中存在

可以像修饰符一样被使用,可用于修饰包、类、构造器、方法等

还可以添加参数值,保存在Annotation的“name = value”中

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

2.注解的应用场景

  • 文档注释
  • 在编译时进行格式检查
  • 跟踪代码依赖性,实现替代配置文件功能

3.Java基础涉及到的三个常用注解

@Override :限定重写父类方法,该注解只能用于方法

@Deprecated:用于表示所修饰的元素已过时。

@SuppressWarnings:抑制编译器警告

4.自定义注解

以@SuppressWarnings为例,进行定义即可

5.元注解的理解:

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

讲4个元注解

  • @Target:用于描述注解的适用范围
  • @Retention:用于描述注解的生命周期
  • @Documented:表明这个注解应该被javadoc工具记录
  • @Inherited:允许子类继承父类中的注解

拓展:单元测试@Test

(重点关注)想要能正确的编写单元测试方法,需要满足:

  • 所在的类必须是public的,非抽象的,包含唯一的无参构造器
  • @Test标记的方法本身必须是public、非抽象的、非静态的,void无返回值、()无参数的

11.包装类

1.为什么使用包装类

为了使得基本数据类型的变量具备引用数据类型变量的相关特征,我们给各个基本数据类型的变量提供了对应的包装类

2.基本数据类型对应的包装类类型

byte - Byte

short - Short

int - Integer

long-Long

double-Double

float-Float

boolean-Boolean

3.掌握两者转换

基本数据类型-->包装类:

①使用包装类的构造器

建议用包装类的valueOf

包装类-->基本数据类型:

调用包装类的xxx.xxxValue()取值

4.String与基本、包装类之间的转换

基本数据类型、包装类-->String数据类型:调用String的重载的静态方法valueOf(xxx xx);String str2 = b1+"";

String类型-->基本、包装类:调用包装类的静态方法parseXxx()

TypeScript
public void test() {
int i1 = 10;
String str1 = String.valueOf(i1);
System.out.println(str1);

boolean b1 = true;
System.out.println(String.valueOf(b1));
String str2 = b1+"";

String str3 = "123";
int i4 = Integer.parseInt(str3);
}
@Test
public void test2(){
double d1= 100;
int int1 = 100;
System.out.println(d1 == int1);
}
@Test
public void test3(){
Object obj = new Integer(1);

System.out.println(obj);

}

posted @ 2026-06-01 21:27  小赵Zzz  阅读(16)  评论(0)    收藏  举报