欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 认识类与对象(下)

认识类与对象(下)

2025/4/23 7:50:33 来源:https://blog.csdn.net/2202_75357702/article/details/143267960  浏览:    关键词:认识类与对象(下)

目录

一.包

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 对象,静态代码块都只执行一次。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词