当前位置: 首页 > article >正文

认识类与对象(下)

目录

一.包

1.导入包中的类

2.自定义包

二.static关键字

1.static修饰成员变量

2.static修饰方法

三.代码块

1.局部代码块

2.构造代码块

2.静态代码块


一.包

就是一组类的组合,用于组织和管理类和接口等代码文件,帮助开发者更好地组织代码,还防止了类名冲突,并提高了代码的可读性和可维护性。


1.导入包中的类

导入包中的类就是java提供的现成的类提供给我们使用,需要我们使用import关键字。导入特定类或整个包。

比如说:

  • java.lang:包含基础类,如StringMathSystem等,默认自动导入。
  • java.util:包含实用工具类和集合框架,如ArrayListHashMapArrays
  • java.io:包含输入/输出类,如FileInputStreamOutputStream
  • java.nio:提供非阻塞I/O操作的类。
  • java.net:支持网络编程的类,如SocketURL
  • java.awtjavax.swing:用于图形用户界面(GUI)编程。
  • 等等

举个例子:

输出结果为:

代码解释:

import java.util.Arrays; :这行代码导入了java.util包中的Arrays类,使我们可以直接使用Arrays类中的各种静态方法,比如sorttoString,来操作数组。

Arrays.sort(arr); :Arrays.sort(arr);是调用Arrays类中的静态方法sort来对数组arr进行排序,该方法使用的是快速排序算法(在大多数情况下)对数组进行排序。

System.out.println(arr); :输出的是数组对象的内存地址哈希码,而不是数组内容。这是因为println直接打印数组引用(对象),而不是它的值。输出类似于[I@1a2b3c4d,其中[I表示这是一个整型数组。

System.out.println(Arrays.toString(arr)); :Arrays.toString(arr);将数组arr转换为可读的字符串格式。Arrays.toString方法将数组的内容以[元素1, 元素2, ...]的形式转换成字符串。


在Java中,如果要使用其他包中的类或方法,通常需要在类名前添加它们所在的包名作为前缀。

具体情况:

1.显式导入类:通过import语句导入一个类后,可以直接使用该类的名称,而不必加上包名前缀。

import java.util.Arrays;  // 导入Arrays类
...
Arrays.sort(arr); // 直接使用Arrays类

2.完整路径(不导入类时):如果没有使用import语句,那么每次调用这个类的方法时都需要写上完整的包路径。

// 没有import java.util.Arrays;
java.util.Arrays.sort(arr); // 需要写完整的路径

3.导入整个包(使用*通配符):使用import java.util.*;可以导入java.util包下的所有类,之后可以直接使用包中任何类的名称(如ArraysArrayList等)。

import java.util.*;  // 导入java.util包中的所有类
...
Arrays.sort(arr);    // 直接使用Arrays类

PS:不过我还是推荐显式导入包,不推荐导入整个包。有些包他们之间有着相同的方法名但是功能是不同的,当我们通过导入整个包来导入他们,这样就有可能导致冲突,因为编译器都不知道你到底是想用哪一个包的方法,执行程序的时候就可能会达不到想要的效果或者编译错误。


当然也有特殊情况不需要在类名前添加它们所在的包名作为前缀。就是使用import static导入包中静态的方法和字段。

如:


2.自定义包

自定义包是由开发者自行定义的包,用于将相关的类和接口按功能进行分组。例如,一个电商应用可以分为用户管理、订单处理和产品管理等不同的功能模块,每个模块可以作为一个独立的包。

示例:

com.myecommerce.user       // 用户相关功能的包
com.myecommerce.order      // 订单处理功能的包
com.myecommerce.product    // 产品管理功能的包


如何创建自定义包?

当然我们在创建包的时候得知道一些规则:

1.在类的开头使用package关键字声明包名。

2.包名通常采用小写字母公司域名反写形式

3.包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/bit/demo1 来存储 代码.

4.如果一个类没有 package 语句, 则该类被放到一个默认包(默认包没有名字,位于项目的根目录下(即不在任何包声明之内)。在这种情况下,类的文件顶部没有 package 语句).

创建步骤:

(图片中的Person类和Test不用理会)

假设我们要创建一个名为com.example.utils的包,并在其中定义一个名为Helper的类

package com.example.utils;:这行代码声明了Helper类属于com.example.utils包。同时我们也在该类中写了一个public类型修饰的方法printHello。


ok,创建完之后如果大家的包是平放的,如图所示:

教一下大家如何分级

效果如图:


创建完之后我们来测试一下,我们在example上面创建一个类(右击example,点new,点Java class,取名为Test):

然后在该类中导入自定义包中的Helper类,并且调用Helper中的方法printHello

输出结果为:

如果我们把类Helper中的printHello的访问修饰符从public修改为protected或者private,在Test类中就会出现报错,尽管你已经导入Helper类:

这里再次给出访问限制符供大家参考:

No范围privatedefaultprotectedpublic
1同一包中的同一类
2同一包中的不同类
3不同包中的子类
4不同包中的非子类

PS(重点):

在 Java 中,位于 com.example.utils 包中的类与位于 com.example 包中的类属于不同的包。这是因为 Java 的包结构是层级化的,每个包都有其独立的命名空间。


包结构的具体说明

命名空间

  • com.example 是一个包,包含在该包中的所有类都可以通过 com.example 包名访问。
  • com.example.utils 是一个子包,它属于 com.example 包,所有在该包中的类可以通过 com.example.utils 包名访问。

不同包的类

位于 com.example.utils 中的类,比如 Utility,

位于 com.example 中的类,比如 Example。

包之间的关系

虽然 com.example.utilscom.example 的子包,但它们是两个不同的包。类 Utilitycom.example.utils 中,而类 Examplecom.example 中。


二.static关键字

1.static修饰成员变量

在类中用 static 关键字修饰的变量。这种变量属于类本身,而不是某个特定的实例


特点:

  • 共享性:所有该类的实例共享同一个静态变量。无论创建多少个对象,静态变量的存储只有一份。

  • 生命周期:静态变量在类加载时被初始化,并在 JVM 关闭时被销毁。它的生命周期与类的生命周期相同。

  • 访问方式:可以通过类名直接访问静态变量,无需创建类的实例。当然也可以通过对象来访问,但是更推荐使用类名来访问。例如:ClassName.staticVariable

  • 初始化:静态变量可以在声明时初始化,也可以通过静态块进行初始化。静态块会在类加载时执行,仅执行一次。


举个例子:

public class Counter {
    static int count = 0; // 静态变量

    public Counter() {
        count++; // 每次创建实例时增加计数
    }

    public static void displayCount() {
        System.out.println("Count: " + count);
    }
}

public class Test {
    public static void main(String[] args) {
        Counter c1 = new Counter(); // 创建第一个实例
        Counter c2 = new Counter(); // 创建第二个实例
        Counter c3 = new Counter(); // 创建第三个实例

        Counter.displayCount(); // 输出: Count: 3
    }
}

可以看出来,count是共享的,每实例化一个对象出来,count都会++。


访问静态变量:

通过实例访问:虽然可以通过实例访问静态变量,但不推荐这样做,因为这可能会导致混淆。示例如下:

Counter c1 = new Counter();
System.out.println(c1.count); // 可以访问,但不推荐

通过类名访问:这是推荐的方式,更清晰明了:

System.out.println(Counter.count); // 正确且推荐的方式

静态变量的初始化:

1.默认初始化(不初始化)

public class Example {
    static int num;
    static boolean flag;
    static String str;
    public static void main(String[] args) {
        System.out.println(num);
        System.out.println(flag);
        System.out.println(str);
        ;
    }
}

结果为:


2.显示初始化

public class Example {
    static int age=10;
    static String name="zhangsan";
    public static void main(String[] args) {
        System.out.println(age);
        System.out.println(name);
    }
}

结果为;


3.静态块初始化(后面讲)

public class Example {
    static int staticVar = 10; // 显示初始化

    static {
        staticVar = 20; // 在静态块中重新初始化
        System.out.println("Static block executed, staticVar: " + staticVar);
    }

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

2.static修饰方法

在类中用 static 关键字修饰的方法。静态方法可以在没有创建类的实例的情况下被调用。


特点:

  • 不依赖于实例:静态方法不依赖于类的实例,因此可以直接通过类名调用,而无需实例化对象,例如 ClassName.methodName()。也可以通过实例对象调用,但不推荐这种方式,因为它可能会导致混淆。

  • 共享性:静态方法在内存中只有一份,所有实例共享这一份。

  • 访问限制:静态方法只能直接访问其他静态变量和静态方法,不能直接访问实例变量和实例方法。这是因为静态方法在调用时不依赖于特定对象的状态。

  • 生命周期:静态方法在类加载时加载,并在类卸载时销毁。其生命周期与类的生命周期相同。


举个例子:

class MathUtils {
    // 静态方法,计算两个数的最大值
    public static int max(int a, int b) {
        return (a > b) ? a : b;
    }
}

public class Main {
    public static void main(String[] args) {
        // 静态方法通过类名调用
        int result = MathUtils.max(10, 20);
        System.out.println("Max: " + result);  // 输出:Max: 20
    }
}

可以看出来,静态方法可以直接通过类名直接访问。


静态方法的限制(具体一点的例子):

class Example1 {
    private int nonStaticVar = 10;  // 非静态成员变量
    private static int staticVar = 20;  // 静态成员变量

    // 非静态方法
    public void nonStaticMethod() {
        System.out.println("This is a non-static method.");
    }

    // 静态方法
    public static void staticMethod() {
        // System.out.println(nonStaticVar);  // 错误,不能在静态方法中访问非静态变量
        // nonStaticMethod();  // 错误,不能在静态方法中调用非静态方法

        System.out.println(staticVar);  // 可以访问静态变量
    }

    public static void main(String[] args) {
        // 直接调用静态方法
        staticMethod();

        // 要访问非静态成员,必须先创建对象
        Example1 example = new Example1();
        System.out.println(example.nonStaticVar);  // 访问非静态变量
        example.nonStaticMethod();  // 调用非静态方法
    }
}

三.代码块

1.局部代码块

局部代码块的语法是使用花括号 {} 包裹的代码,它在方法内部出现。


特点:

  • 作用范围:局部代码块的作用范围仅限于方法内部。当方法执行结束或代码块外的作用域结束时,局部代码块中的变量也会被销毁。
  • 生命周期:局部代码块的生命周期仅在方法调用过程中。方法每次调用时局部代码块都会重新执行。
  • 独立性:局部代码块通常用于缩小变量的作用域或进行流程控制,不涉及类级别的初始化或对象创建的初始化。

举个例子:

public class Test {
    public void exampleMethod() {
        System.out.println("Method start");

        // 局部代码块
        {
            int localVariable = 5;
            System.out.println("方法内部 localVariable = " + localVariable);
        }

        // 这里无法访问 localVariable,因为它的作用范围仅限于局部代码块内部
        // System.out.println(localVariable); // 编译错误
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.exampleMethod();
    }
}

输出为:


2.构造代码块

构造代码块也称为实例代码块)是使用花括号 {} 包裹的一段代码,它直接写在类中,而不是在方法或构造方法中


特点:

  • 复用性:如果所有构造方法中需要执行相同的初始化代码,可以将这些代码放入构造代码块中,避免在每个构造方法中重复写相同的代码。
  • 访问实例变量:构造代码块可以访问实例变量,因为它在对象创建时执行。

普通代码块的用途:

  • 实例变量的初始化:可以在构造代码块中对实例变量进行一些复杂的初始化操作。

  • 通用代码的复用:如果多个构造方法中需要执行相同的初始化代码,可以将这些代码写在构造代码块中,避免在每个构造方法中重复写相同的代码。


执行时机:

  • 构造代码块在每次创建对象(实例化)时都会执行。
  • 它的执行优先级比构造方法高,但在构造方法之前执行。
  • 每次创建一个新的对象时,构造代码块都会被执行一次,即使构造方法不同。

举个例子:

class Example {
    private int x;

    // 构造代码块,用于初始化实例变量 x
    {
        x = 10;
        System.out.println("构造代码块输出 x = " + x);
    }

    // 第一个构造方法
    public Example() {
        System.out.println("构造方法输出");
    }

    // 第二个构造方法
    public Example(int x) {
        this.x = x;
        System.out.println("构造方法2输出 x = " + this.x);
    }
}

public class Main {
    public static void main(String[] args) {
        Example example1 = new Example();      // 输出: 构造方法输出
        Example example2 = new Example(20);    // 输出: 构造方法2输出 x = 20
    }
}

输出结果为:

代码解释:

  • 当创建 Example 类的实例时,普通代码块会首先执行,将 x 初始化为 10。
  • 然后,构造方法才会被调用。
  • 如果传入了参数,则构造方法会覆盖普通代码块对 x 的初始化。

2.静态代码块

静态代码块(Static Block)是用 static {} 包裹的一段代码。静态代码块在类加载时执行只执行一次,通常用于静态变量的初始化执行与类相关的操作。'


特点:

  • 与类关联:静态代码块与类关联,在 JVM 加载类时执行,而不是在创建实例时执行。
  • 只执行一次:静态代码块在类加载时执行一次,并且整个程序运行期间不会再次执行。
  • 用于静态变量的初始化:可以在静态代码块中初始化静态变量,或者执行需要在类加载时完成的操作。

静态代码块的用途:

  • 静态变量初始化:静态代码块常用于静态变量的初始化,特别是当初始化需要执行复杂逻辑时。
  • 执行与类相关的静态操作:在静态代码块中可以执行与类相关的静态操作,比如数据库连接、加载配置文件等。

执行时机:

  • 类加载时执行:静态代码块在类加载到内存时执行,仅执行一次。
  • 优先于对象实例化:静态代码块的执行优先级比构造方法和实例代码块更高,因此在任何对象实例化之前执行。

举个例子:

public class Test {
    static int staticVariable;

    // 静态代码块,用于初始化静态变量
    static {
        staticVariable = 10;
        System.out.println("静态代码块执行 staticVariable = " + staticVariable);
    }

    // 构造方法
    public Test() {
        System.out.println("构造方法执行");
    }

    public static void main(String[] args) {
        System.out.println("主函数执行");
        Test example1 = new Test();  // 创建第一个对象
        Test example2 = new Test();  // 创建第二个对象
    }
}

输出结果为:

代码解释:

  • 静态代码块在类加载时执行一次,初始化 staticVariable
  • 之后,main 方法开始执行,两个对象的构造方法分别被调用。
  • 无论创建多少个 Example 对象,静态代码块都只执行一次。

http://www.kler.cn/a/378176.html

相关文章:

  • Gaea学习笔记总结
  • LightGBM分类算法在医疗数据挖掘中的深度探索与应用创新(上)
  • Android学习(五)-Kotlin编程语言-面向对象中的 继承-构造函数-接口三模块学习
  • RHEL 7.5 源码安装 mysql-5.7.17 数据库
  • 计算机毕业设计原创定制(免费送源码):NodeJS+MVVM+MySQL 樱花在线视频网站
  • MacOS安装MySQL
  • 算法——递推
  • 组织架构图
  • Linux: network: hw csum failure
  • 【ceral】c++轻量的序列化库
  • 2024 年( 第五届)“ 大湾区杯” 粤港澳金融数学建模竞赛A 题
  • 背包问题的详细理解(无基础->详细掌握)
  • Ubuntu 24 配置vsftp
  • SpringBoot抗疫物资管理与数据分析系统
  • vulhub之Spring篇
  • AIGC与虚拟现实(VR)的结合与应用前景
  • 人工智能中FOPL语言是什么?
  • php实现sl651水文规约解析
  • 自定义view实现历史记录流式布局
  • 5G基础知识
  • 【51 Pandas+Pyecharts | 深圳市共享单车数据分析可视化】
  • Java爬虫:京东商品SKU信息的“窃听风云”
  • 消息中间件类型介绍
  • 共创一带一路经济体,土耳其海外媒体软文发稿 - 媒体宣发报道
  • nodejs入门教程9:nodejs Buffer
  • Vue学习笔记(十一)