类变量与类方法

static修饰的成员变量(类变量,静态变量)的特性?

同一个类所有对象共享

类变量是随着类的加载而创建, 所以即使没有创建对象实例也可以访问 ,但是类变量的访问, 必须遵守 相关的访问权限.

static可以修饰类或者函数吗?

可以,使用static修饰的方法称为类方法或静态方法。

static方法可以被重写吗?

静态方法可以被继承,但是,不能被覆盖,即重写。如果父类中定义的静态方法在子类中被重新定义,那么在父类中定义的静态方法将被隐藏。可以使用语法:父类名.静态方法调用隐藏的静态方法。

如果父类中含有一个静态方法,且在子类中也含有一个返回类型、方法名、参数列表均与之相同的静态方法,那么该子类实际上只是 将父类中的该同名方法进行了隐藏,而非重写。 换句话说,父类和子类中含有的其实是两个没有关系的方法,它们的行为也并不具有多态性。

因此,通过一个指向子类对象的父类引用变量来调用父子同名的静态方法时,只会调用父类的静态方法。

所以父类和子类中同名同参数的方法:要么全声明成static的【不考虑重写】;要么全声明成非static的【考虑重写】

静态变量与成员变量的区别?

特性 静态变量(类变量) 成员变量(实例变量)
声明方式 使用static关键字修饰 不使用static关键字
所属范围 属于类,所有实例共享 属于对象实例,每个实例独有一份
内存分配时机 类加载时分配内存 创建对象实例时分配内存
内存位置 方法区(元空间)中的静态区 堆内存
初始化时机 类加载时初始化 对象创建时初始化
生命周期 从类加载到程序结束 从对象创建到被垃圾回收
访问方式 可通过类名直接访问 必须通过对象实例访问
线程安全性 需要考虑线程安全问题 每个线程有自己的实例,相对安全
默认值 与成员变量相同(0, false, null等) 与静态变量相同

静态变量的两种访问方式?

一般什么情况下会将方法使用static设置静态方法?

理解 main 方法语法

如何理解java的main()函数?

代码块

static代码块与普通代码块的区别?

特性 static代码块(静态初始化块) 普通代码块(实例初始化块)
关键字 使用static修饰 无特殊关键字
执行时机 类加载时执行(仅一次) 每次创建对象实例时执行
执行次数 整个程序生命周期只执行一次 每次实例化对象都会执行
访问权限 只能访问静态成员 可以访问静态和非静态成员
内存位置 方法区(元空间) 堆内存
主要用途 初始化静态变量或执行静态初始化逻辑 初始化实例变量或执行对象公共初始化逻辑
执行顺序 类加载时最先执行 在构造方法之前执行

普通代码块在类加载时会执行吗?

普通代码块(非静态代码块)在类加载时不会执行。普通代码块只会在创建类的实例对象时执行,且每次创建对象时都会执行一次。

类加载的时机

创建类的实例:使用new关键字创建对象时

访问类的静态成员:包括静态变量和静态方法

使用反射:通过Class.forName()等方法

初始化子类:当子类被初始化时,其父类也会被加载。创建子类对象实例, 父类也会被加载, 而且, 父类先被加载, 子类后被加载

class Parent {}
class Child extends Parent {} // 初始化Child时Parent也会被加载

作为主类:包含main()方法的类在程序启动时被加载

Java中创建一个对象时类内部各部分的初始化顺序

  1. 静态代码块和静态变量初始化的优先级相同

    • 它们按照在类中定义的先后顺序执行
    • 这部分只在类第一次被加载时执行一次,之后再加载时第一部分不会加载,只会加载后面两部分
  2. 普通代码块和普通属性初始化的优先级相同
    • 同样按照定义顺序执行
  3. 构造方法总是最后执行
    • 在所有初始化工作完成后才执行构造方法
记忆技巧
  1. 先静态后实例:先处理所有静态的,再处理实例相关的
  2. 同级按顺序:同级别的代码块和初始化按定义顺序执行
  3. 构造最后走:构造方法总是最后一步执行


单例设计模式

什么是设计模式?

什么是单例设计模式?

单例设计模式的两种实现方法?

饿汉式

懒汉式

饿汉式 VS 懒汉式

Java中final关键字的用法总结

1. final修饰属性(常量)

  • final修饰的属性称为常量,命名规范:全部大写字母,单词间用下划线连接(如MAX_VALUE
  • 必须赋初值,且后续不能修改,赋值位置三选一:
    1. 定义时直接赋值public final double TAX_RATE = 0.08;
    2. 在构造器中赋值
    3. 在代码块中赋值

2. final修饰静态属性

  • 如果是static final修饰的静态常量,初始化位置只能是:

    1. 定义时直接赋值

    2. 在静态代码块中赋值

      注意:不能在构造器中赋值

      构造器是在创建对象的时候才会被调用,而使用final修饰静态属性需要在类加载时就要赋值,所以不能在构造器中初始化。

3. final修饰类

  • final不能被继承(不能有子类)

  • 可以实例化对象

    示例:

    java

    复制

    final class A2 {}  // 不能被继承
    A2 obj = new A2(); // 可以创建对象

4. final修饰方法

  • 如果类不是final类但包含final方法:

    • 该方法不能被子类重写
    • 可以被继承使用

5. final类与final方法的关系

  • 如果一个类已经是final类(不能被继承),那么:

    • 不需要再将其方法修饰为final方法
    • 因为final类本身禁止继承,所有方法自然也无法被重写

6. final与构造方法

  • final不能修饰构造方法(构造器)

    • 构造方法本身就不能被继承或重写
    • 语法上不允许使用final修饰构造器

7. final与static的搭配使用

  • final和static经常组合使用(static final)

  • 优势:

    1. 效率更高:编译器会进行优化处理
    2. 避免类加载:使用static final常量不会导致类的初始化

    参考《类加载的时机》访问类的静态成员:包括静态变量和静态方法类会被加载。

8. Java核心类中的final应用

  • 包装类都是final类

    • Integer, Double, Float, Boolean等
  • String类也是final类
    • 这些类设计为final是为了保证核心功能的安全性和不可变性

抽象类

为什么父类方法访问修饰符为 private/final/static 则子类就不能重写该方法

private 修饰符:

private 修饰的方法是私有方法,只能在当前类中访问,子类无法访问到这个方法,更不用说重写了。

final 修饰符:

final 修饰的方法表示该方法是最终版本,不允许被子类重写。如果子类尝试重写一个被 final 修饰的方法,编译器会报错。

static 修饰符:

在Java中,static方法属于类级别,这意味着它们与特定的实例对象无关,而是与整个类相关联。当你调用一个static方法时,你是通过类名来调用它,而不是通过实例对象。因此,static方法在编译时就确定了调用哪个方法,而不是在运行时根据实例对象的类型来确定。

而子类重写父类方法的过程是通过动态绑定(也称为运行时多态)来实现的。这意味着在运行时,通过实例对象的类型来确定调用的方法。

由于static方法的调用在编译时就确定了,而不是在运行时确定,所以子类无法重写父类的static方法。子类可以定义与父类static方法同名的方法,但这只是在子类中隐藏了父类的方法,并不能称之为重写

接口

接口的特性与实现

1. 接口不能被实例化(抽象类也不能被实例化)
  • 知识点:接口不能被实例化。
  • 解释:接口是一种抽象类型,不能直接创建对象。它需要通过类来实现其定义的方法。
2. 接口中的方法
  • 知识点

    • 接口中所有的方法默认是 public 的。 (不写public也行,这样默认为public)
    • 接口中的抽象方法可以省略 abstract 关键字。
  • 示例
    void aaa();  // 实际上是 public abstract void aaa();
    • 注意:接口中不能有方法体(所有的方法都不能有方法体,即不能有实现)。
    • 错误示例:
      void aaa(){}  // 错误!接口中不能包含具体实现。
3. 普通类实现接口
  • 知识点:一个普通类实现接口时,必须实现接口中定义的所有方法。 (IDEA中使用alt+enter快速实现接口)
  • 解释:普通类需要为接口中的每个抽象方法提供具体的实现,否则会编译错误。
4. 抽象类实现接口
  • 知识点:抽象类实现接口时,可以选择不实现接口中的方法。
  • 解释:抽象类本身可以包含抽象方法,因此可以将接口的抽象方法延迟到子类中实现。

接口中属性和方法的区别

特性 方法 属性
默认修饰符 public abstract(可省略) public static final(可省略)
是否需实现 普通类必须实现 无需实现(常量不可修改)
访问方式 通过实现类实例调用 通过接口名直接访问(如 接口名.属性名
初始化要求 无方法体(抽象方法) 必须显式初始化

阿里巴巴开发规范中提到:

  1. 多实现:一个类可同时实现多个接口(解决单继承局限)。

    class Dog implements Runnable, Barkable {}
  2. 一个类可同时继承父类且实现多个接口。

    class LittleMonkey extends Monkey implements Fishable,Birdable{}
  3. 接口继承:接口可继承多个父接口(但不能继承类)。

    interface A extends B, C {}
  4. 修饰符限制:接口的修饰符仅限 public 或默认(包访问权限)。

如何理解接口的多态特性?

接口的多态是面向对象编程的核心特性之一,它允许同一接口引用指向不同实现类的对象,从而在运行时动态调用具体实现。以下是接口多态的三种典型体现:


1. 多态参数(灵活接收不同实现对象)
  • 核心思想:接口类型作为方法参数,可以接收任何实现了该接口的类的对象。
  • 示例InterfacePolyParameter.java):
    interface UsbInterface {
    void start();
    void stop();
    } class Phone implements UsbInterface {
    public void start() { System.out.println("手机连接USB"); }
    public void stop() { System.out.println("手机断开USB"); }
    } class Camera implements UsbInterface {
    public void start() { System.out.println("相机连接USB"); }
    public void stop() { System.out.println("相机断开USB"); }
    } public class Test {
    // 多态参数:方法接收UsbInterface类型,实际传入Phone或Camera对象
    public static void work(UsbInterface usb) {
    usb.start();
    usb.stop();
    } public static void main(String[] args) {
    work(new Phone()); // 输出手机逻辑
    work(new Camera()); // 输出相机逻辑
    }
    }
  • 关键点
    • 方法work()无需关心具体是Phone还是Camera,只需调用接口定义的方法。
    • 新增设备类(如Keyboard)时,只需实现UsbInterface,无需修改work()方法。

2. 多态数组(统一管理不同实现对象)
  • 核心思想:通过接口类型数组,存储多种实现类的对象,并统一处理。
  • 示例InterfacePolyArray.java):
    UsbInterface[] usbs = new UsbInterface[2];
    usbs[0] = new Phone(); // 存放手机对象
    usbs[1] = new Camera(); // 存放相机对象 for (UsbInterface usb : usbs) {
    usb.start();
    usb.stop();
    // 调用Phone特有方法:需类型判断和向下转型
    if (usb instanceof Phone) {
    ((Phone)usb).call(); // 调用Phone的call()
    }
    }
  • 关键点
    • 数组usbs统一管理所有UsbInterface实现类。
    • 通过instanceof判断具体类型,访问实现类特有方法(如call())。

3. 多态传递(接口继承时的多态)
  • 核心思想:接口类型的引用可以指向实现了该接口的子接口或实现类的对象。
  • 示例InterfacePolyPass.java):
    interface A { void f1(); }
    interface B extends A {} // 子接口继承父接口
    class C implements B {
    public void f1() { System.out.println("实现f1"); }
    } public class Test {
    public static void main(String[] args) {
    A a = new C(); // 父接口引用指向实现类对象
    a.f1(); // 输出"实现f1"
    }
    }
  • 关键点
    • 子接口B继承A后,实现类C必须实现所有父接口方法。
    • 父接口类型(如A)可以接收子接口或实现类的对象。

Java内部类与外部类

类的五大成员

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

内部类,外部类,外部其他类举例

class Outer {  // 外部类:Outer
class Inner { // 内部类:Inner
}
}
class Other { // 外部其他类:Other
}

内部类的分类

1.局部内部类(有类名)
  • 定义在方法或代码块中,有显式的类名。
  • 不能添加访问修饰符(如public/private),因其地位等同于局部变量。允许final修饰(与局部变量规则一致)。
  • 作用域仅限于所在方法或代码块。
  • 可直接访问外部类的所有成员(包括私有成员)。访问方式:直接调用(无需特殊语法)。
  • 外部类访问局部内部类成员,必须在局部内部类的作用域内(定义它的方法或代码块)创建对象后访问。
  • 外部其他类不能访问局部内部类,因为局部内部类的地位是一个局部变量。
  • 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,可以使用(外部类名.this.成员)去访问。外部类名.this:代表外部类的当前实例对象。

代码演示

class Outer {
private int num = 10; // 外部类成员变量 public void method() {
class LocalInner {
int num = 20; // 局部内部类成员变量(与外部类重名) public void show() {
System.out.println(num); // 默认访问局部内部类的num(输出20)
System.out.println(Outer.this.num); // 显式访问外部类的num(输出10)Outer.this 本质就是外部类的对象, 即哪个对象调用了 method, Outer.this 就是哪个对象。本例中Outer.this是outer_example
}
} LocalInner inner = new LocalInner();
inner.show();
}
} public class Test {
public static void main(String[] args) {
Outer outer_example = new Outer();
outer_example.method();
}
}
2.匿名内部类(无类名,重点!)

匿名:没有名字的意思。内部类:写在其他类内部的类。匿名内部类的作用是简化代码。

原本我们需要创建子类或者实现类,去继承父类(包含抽象类)和实现接口,才能重写其中的方法。但是有时候我们这样做了,然而子类和实现类却只使用了一次(定义了一个对象)。这个时候我们就可以使用匿名内部类,不用去写子类和实现类,起到简化代码的作用。

匿名内部类的格式:父类/接口 对象 = new 父类/接口(){ 重写父类/接口中的方法 };

这样做就把子类继承父类,重写父类中的方法,创建子类对象,合成了一步完成,减少了其中创建子类的过程。或者将实现类实现接口,重写接口中的方法,创建实现类对象,合成了一步完成,减少了其中创建实现类的过程。下面将会用代码演示如何使用匿名内部类。

匿名内部类实现接口或抽象类是否需要重写所有抽象方法?

需要。匿名内部类在实现接口时,必须重写接口中定义的所有抽象方法。

3.成员内部类(无static修饰)
  • 属于外部类的实例成员,可访问外部类的所有实例变量和方法。
  • 必须先创建外部类对象才能实例化。
4.静态内部类(有static修饰)
  • 属于外部类的静态成员,仅能访问外部类的静态成员。
  • 可直接通过外部类名访问,无需外部类实例。
5.内布类比较
特性 局部内部类 匿名内部类 成员内部类 静态内部类
定义位置 外部类的方法或代码块内 外部类的方法或代码块内 外部类的成员位置(非静态) 外部类的成员位置(静态)
访问修饰符 不能添加(仅允许final修饰) 不能添加 可添加(如public/private 可添加(如public/private
作用域 仅限于定义它的方法或代码块 仅限于定义它的方法或代码块 整个外部类 整个外部类
访问外部类成员 直接访问所有成员(包括私有成员) 直接访问所有成员(包括私有成员) 直接访问所有成员(包括私有成员) 仅能访问静态成员(包括私有成员)
外部类访问内部类 需在作用域内创建对象访问 无法直接访问(匿名无类名) 需通过外部类实例创建内部类对象 可直接访问(无需外部类实例)
外部类与内部类成员重名时的访问规则 就近原则,外部类名.this.成员名 就近原则,外部类名.this.成员名 就近原则,外部类名.this.成员名 就近原则,外部类名.静态成员名

第10章面向对象编程(高级部分)-cnblog的更多相关文章

  1. 大数据技术之_16_Scala学习_06_面向对象编程-高级+隐式转换和隐式值

    第八章 面向对象编程-高级8.1 静态属性和静态方法8.1.1 静态属性-提出问题8.1.2 基本介绍8.1.3 伴生对象的快速入门8.1.4 伴生对象的小结8.1.5 最佳实践-使用伴生对象解决小孩 ...

  2. Objective-C 基础教程第三章,面向对象编程基础知

    目录 Objective-C 基础教程第三章,面向对象编程基础知 0x00 前言 0x01 间接(indirection) 0x02 面向对象编程中使用间接 面向过程编程 面向对象编程 0x03 OC ...

  3. 《Python 3.5从零开始学》笔记-第8章 面向对象编程

    前几章包括开启python之旅.列表和元组.字符串.字典.条件和循环等语句.函数等基本操作.主要对后面几章比较深入的内容记录笔记. 第8章 面向对象编程 8.3深入类 #!/usr/local/bin ...

  4. 那些年被我坑过的Python——玄而又玄(第六章 面向对象编程基础)

    面向对象编程: 面向对象顾名思义,就是把组织代码的粒度从函数级别抽象到对象级别,对象是通过类来生成的,类可以想象为模板或进本框架而对象是在原有模板或框架的基础上增加详细信息的实体,类,有分类.聚类的含 ...

  5. js面向对象编程-高级内容

    JavaScript面向对象 一.为每个对象动态添加属性或方法 功能:返回对象类型原型的引用 prototype的使用 格式:class.prototype 场景: 比如说:A写了一个类,交给B,B在 ...

  6. Python面向对象编程高级特性

    ***这里还是根据网上资料,主要是廖雪峰老师的教程学习的笔记,主要介绍python面向对象的高级特性,笔记不全,只是记录自己觉得容易出错的地方*** 1.python作为一种动态语言,他的动态绑定机制 ...

  7. #《Essential C++》读书笔记# 第五章 面向对象编程风格

    基础知识 继承机制定义了父子(parent/child)关系.父类(parent)定义了所有子类(children)共通的共有接口(public interface)和私有实现(private imp ...

  8. Java面向对象笔记 • 【第10章 Swing编程初级应用】

    全部章节   >>>> 本章目录 10.1 JFrame窗口容器 10.1.1 Swing介绍 10.1.2 JFrame窗口容器应用 JFrame常用方法 10.1.3 实践 ...

  9. 第10章 Shell编程(2)_字符截取命令

    2. 字符截取命令 2.1 cut字段提取命令(grep提取行,cut提取列) (1)cut命令:#cut [选项] 文件名 选项: -f 列号:提取第几列: -d 分隔符:按照指定分隔符分割列,默认 ...

  10. 8. Scala面向对象编程(高级部分)

    8.1 静态属性和静态方法 8.1.1 静态属性-提出问题 有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在共有多少人在玩?请使用面向对象的思想,编写程序解决 8.1.2 基本介绍 -Sca ...

随机推荐

  1. Pulsar客户端如何控制内存使用

    摘要 本文围绕一个常见的使用场景深入分析在高吞吐场景下,使用Pulsar客户端收发消息可能会遇到的若干问题.并以此为切入点,梳理一下Pulsar客户端在内存控制上所做的优化改进. 使用场景 假设这样一 ...

  2. w3cschool-Netty 实战精髓篇1

    https://www.w3cschool.cn/essential_netty_in_action/ Netty 异步和数据驱动 2021-04-22 14:57 更新 在学习Netty的异步和数据 ...

  3. CentOS7离线安装Nginx及配置

    下载离线包: 用浏览器打开地址,选择您要下载的版本:http://nginx.org/packages/centos/7/x86_64/RPMS/ 如图,我下载的1.16.1版. 执行安装: 将下载的 ...

  4. Web访问过程

    WEB访问的具体过程: 命令 浏览器中查看DNS chrome://net-internals/#dns 查看本地DNS ipconfig/displaydns 查看HOST文件 C:\Windows ...

  5. Django项目实战:从安装到启动服务

    Django项目实战:从安装到启动服务 安装Django 首先,确保你已经安装了 Python 和 pip.然后,使用以下命令来安装 Django : pip install django 安装成功后 ...

  6. 洛谷B3843 [GESP202306 三级] 密码合规 题解

    原题传送门 前言 咳咳,由于本人最近在备考GESP三级,所以可能会有很多水的题解.(见谅--见谅--) 由于今天刚刚重新刷了一遍此题,所以记忆犹新.(太菜了!一个测试点都能 WA ) 题目解析 简单的 ...

  7. Typecho去除更新检测和后台日志

    Typecho去除官方日志 打开 admin/index.php,找到下面的代码并删除,在 93-102 行. 代码: <div class="col-mb-12 col-tb-4&q ...

  8. docker - [02] 安装部署

    一.环境准备 1.需要会一点点Linux基础 2.CentOS 7+ 3.XShell连接服务器进行远程操作 Centos7.x 虚拟机环境 序号 主机名 IP 操作系统 1 ctos79-01 19 ...

  9. C++最基本调用动态链接库dll方法的小结

    针对当时初学动态链接.静态链接,有些文档整理一下发出来算是给自己和读者一个小结. 首先创建DLL 编辑头文件 dllmain.h 头文件: #pragma once #if defined(_DLL_ ...

  10. VMware虚拟机上安装CentOS8详细教程

    1.准备工作 1.1.需要准备好已安装完成的VMware虚拟机,如果您的电脑未安装VMware虚拟机,请参考以下连接:https://www.cnblogs.com/x1234567890/p/148 ...