6.类与对象(二)


总结

本章写了封装、static成员以及代码块。



一、封装

1.封装的概念

封装简单来说就是被密封起来(不让我们看见的东西),即被隐藏

对于用户来说,并不需要关心的类,所实现的细节就会被封装(隐藏)。

犹如密封的纸盒子

2.封装的实现方式

1.隐藏内部状态(属性私有化)

将类的成员变量(属性)用private修饰,使其只能在当前内部访问,外部无法直接访问修改或者读取。

2.暴露公共接口(提供访问方法)

通过public修饰的getter(读取)和setter(修改)方法,对外提供属性的访问入口,并在方法中可以添加逻辑校验,控制数据的合法性。

实例:

定义了一个People类中含有封装

public class People {public String name;
//    1.属性私有化(外部无法直接访问)private int age;/*private只能在当前类被访问,当前类的私有属性*///    2.提供公共的getter方法(读取属性)public int getAge() {return age;}//    3.提供公共的setter方法(修改属性可添加校验逻辑 )public void setAge(int age) {
//        校验年龄为合理范围内if (age >= 0 && age <= 200) {this.age = age;}else {System.out.println("年龄无效");}}
}

再次定义了一个测试类运行它

public class Test {public static void main(String[] args) {People people = new People();people.name = "小华";
//        无法直接访问private属性people.setAge(23);System.out.println("请告诉我这个人叫什么?"+" "+people.name);System.out.println("多少岁?"+" "+people.getAge());}
}

getter方法也可以叫做取值方法,setter方法也可以叫做赋值方法。上一篇文章有详细的介绍5.Java类与对象。

3.封装的核心作用

1.数据的安全性

禁止外部直接修改属性通过setter方法的校验逻辑保证数据的合法。举个例子:银行里面存的钱,他人看不见我所存的具体金额,我也修改不了我的数据,这样就保证了社会的稳定,也保证了我的钱的安全性。

2.隐藏实现的细节

外部只需要知道如何通过公共方法使用类,无需关心内部属性的存储方式或逻辑降低耦合度。

3.代码的可维护性

若内部实现需要修改(如校验规则调整),只需修改类内部的方法,外部调用代码无需变动。

4.控制访问权限

3.访问权限控制符

public(公共的):全局可见,可以理解成一个人的外貌特征,谁都可以看见

protected:本包或者子类可见,主要是在继承中

default(包访问权限):本包可见,对于自己家族(同一个包中)不是秘密,对于他人来说就是隐私

private:仅本类可见

4.包

为了更好的管理类,把多个类搜集在一起成为一组,称为软件包

在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口的很好的组织方式。使用包主要是避免类名的冲突、便于代码管理和访问控制,确定类的唯一性。

假如两个程序员不约而同地建立了 Employee类。 只要将这些类放置在不同的包中, 就不会产生冲突。



1.本质:其实就是相当于类的“文件夹”,通过层级结构(类似文件系统的目录)组织类。

2.命名规范:通常使用小写字母,采用反转的域名作为前缀(避免全局冲突),例如:com.exmple.myapp。

层级之间用  分隔,对应文件系统的目录层级(如com/example/myapp)。

3.包的声明

在Java源文件的第一行,用package语句声明该类所属的包。犹如上图。

若未声明package,类会被放入默认包(不推荐,易导致冲突)

5.导入包中的类

一个类可以使用所属包中的所有类, 以及其他包中的公有类(public class)。我们可以采用两种方式访问另一个包中的公有类。


1.在每个类名之前添加    完整的包名 + 类名

2.使用 import 语句(一旦使用了 import 语句,在使用类时,就不必写出包的全名了)

可以使用 import 语句导人一个特定的类或者整个包。import 语句应该位于源文件的顶部(但位于 package 语句的后面)。

3.导入整个包的所有类(不推荐,可能引发冲突)

import com.test.demo1.*;//导入demo1这个包中所有的类

在大多数情况下, 只导入所需的包, 并不必过多地理睬它们。但在发生命名冲突的时候, 就不能不注意包的名字了。 例如,java.util 和java.sql 包都有日期 ( Date) 类。 如果在程序中导入了这两个包:

import java.util.*;

import java.sql.*;

就会报错

此时编译器无法确定程序使用的是哪一个 Date 类。

那我们怎么解决

可以采用增加一个特定的 import 语句来解决这个问题:

这样就不会报错。

如果这两个 Date 类都需要使用, 又该怎么办呢?

答案是,在每个类名的前面加上完整的包名。

4.静态导入

import 语句不仅可以导人类,还增加了导人静态方法和静态域的功能。
就可以使用 Math 类的静态方法和静态域,而不必加类名前缀

import static java.lang.Math.*;
public class TestDemo3 {public static void main(String[] args) {double a = 1.69;double b = 1.96;
//        不导入静态包的写法
//        double sqrtSum = Math.sqrt(a)+Math.sqrt(b);/*(sqrt是根号)1.3+1.4*/double sqrtSum = sqrt(a)+sqrt(b);System.out.println(sqrtSum);}
}

5.常见的包

1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。核心类(String、Object、基本类型包装类)

2. java.lang.reflect:java 反射编程包;

3. java.net:进行网络编程开发包。

4. java.sql:进行数据库开发的支持包。

5. java.util:是java提供的工具程序包。(集合类等) 非常重要

6. java.io:I/O编程开发包,输入输出类(文件操作、流等)


二、static成员

1.static修饰成员变量

static修饰的成员变量,被称为静态成员变量

静态成员变量最大的特性:不属于具体的对象,是所有对象所共享的。

1.特性

①属于类的本身,而非某个具体的对象,所有对象共享一份数据

②生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)

③即可通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问

public class Cat {public String name;public int age;public String color;public double weight;public static int foot = 4;public void eat(){System.out.println(name+"正在吃猫粮");}public void miao(){System.out.println(name+"会喵喵叫");}public static void main(String[] args) {Cat cat1 = new Cat();Cat cat2 = new Cat();cat1.name = "布丁";cat2.name = "大橘";
//        1.通过类名访问System.out.println(Cat.foot);
//        2.通过对象访问System.out.println(cat1.foot);System.out.println(cat2.foot);}
}

④类变量存储在方法区内

2.static修饰成员方法

1.定义

用static修饰的方法属于类不依赖于对象存在

静态方法代表类级别的行为,而不是某个对象的行为。

2.访问方式

通过类名.方法名调用,不能直接访问非静态成员(非静态成员属于对象)

注意:静态方法中不能使用this或者super(因为与对象无关,而this和super需要传递参数)

3.static成员变量初始化

注意:静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性

1. 就地初始化

就地初始化指的是:在定义时直接给出初始值

2.静态代码块初始化

下方有讲


三、代码块

1.普通代码块

定义在方法里面的代码块(直接使用{}定义)

public class TestDemo4 {public static void main(String[] args) {{
//           直接定义在{}里面的代码块,普通代码块int a = 10;System.out.println(a);}int a = 100;System.out.println(a);}
}

2.构造块

构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量。
 

public class Student {
//    实例变量public String name;public int age;public String grage;public double height;public  double weight;public void doClass(){System.out.println(name+"正在学习");}{
//        2.实例代码块this.name = "小杨";this.age = 18;this.grage = "高三";this.height = 180.4;this.weight = 130.5;System.out.println(name+"正在吃饭");}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", grage='" + grage + '\'' +", height=" + height +", weight=" + weight +'}';}public static void main(String[] args) {Student student = new Student();System.out.println(student.toString());}
}

注意:实例代码块只有创建对象时才会执行

3.静态块

定义:使用static定义的代码块

静态块是Java类中用于初始化静态成员的特殊代码块,它在类加载时自动执行。静态块的主要特点包括:

  1. 语法结构: static { // 初始化代码 }

  2. 执行时机:

    • 在类被首次加载时执行
    • 在静态变量初始化之后执行
    • 在main方法执行之前执行
  3. 重要特性:

    • 静态代码块不管生成了多少个对象,其只会执行一次
    • 静态成员变量是类的属性,因此在JVM加载类时开辟空间并初始化的
    • 每个类可以有多个静态块,按声明顺序执行(合并)
    • 不能访问非静态成员
    • 不能抛出已检查异常
    • 不能包含return语句
public class Cat {public String name;public int age;public String color;public double weight;public static int foot = 4;public static int averageLifespan;//    静态代码块:初始化静态属性,类加载时执行static {System.out.println("Cat类正在加载...");averageLifespan = 15;/*假设*/System.out.println("静态代码已执行:初始化寿命为"+averageLifespan+"年");}
//    构造方法(创建实例时执行)public Cat(String name) {this.name =name;System.out.println("创建了猫:"+name);}public static void main(String[] args) {//        第一次使用Cat类静态代码块执行Cat cat = new Cat("布丁");System.out.println("猫平寿:"+averageLifespan+"年");
//        静态代码块不再执行System.out.println("=====");Cat cat1 = new Cat("犀利哥");}}

Qustion:静态代码块和构造代码块(实例代码块)以及构造方法同时存在时,怎么被执行的?其顺序是怎样的?

思考一下,下面的代码将被怎么执行?

public class Dog {public String name;public String species;public String color;public int age;static {System.out.println("静态代码块2");}static {System.out.println("静态代码块1");}static {System.out.println("静态代码块3");}{System.out.println("实例代码块2");}{System.out.println("实力代码块1");}public Dog(String name, String species, String color, int age) {this.name = name;this.species = species;this.color = color;this.age = age;System.out.println("构造方法");}public static void main(String[] args) {Dog dog = new Dog("小花","中华田园犬","黑白",12);System.out.println("=============下面是第二次执行");Dog dog1 = new Dog("小黄","中华田园犬","黄色",13);}
}

其结果是这样的

第一次时

静态代码块被执行(按顺序执行)

实例代码块被执行

构造代码块被执行

第二次

实例代码块被执行

构造代码块被执行

即静态代码块只被执行一次。

4.同步代码块

四、方法toString 

toString方法是Object类的一个方法,用于返回对象的字符串表示。方便调试、打印或者日志记录。

简单来说toString方法就像是构造方法的输出语句,即可以直接输出像Student类中的name, age, grage , height , weight 这些即成员属性。

public class Student {
//    实例变量public String name;public int age;public String grage;public double height;public  double weight;public void doClass(){System.out.println(name+"正在学习");}{
//        2.实例代码块this.name = "小杨";this.age = 18;this.grage = "高三";this.height = 180.4;this.weight = 130.5;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", grage='" + grage + '\'' +", height=" + height +", weight=" + weight +'}';}public static void main(String[] args) {Student student = new Student();System.out.println(student.toString());}
}

toString 方法可以在IDEA中有快捷生成方法键

就可以生成了。

1.默认行为(不重写)

我们可以点击输出中的println,他来看看他的底层代码(Ctrl键+鼠标右击)

我们进入了他的代码中,再点击Object类看看(Ctrl键+鼠标右击)

就进入到了Object类中,这个就是Object类中默认的toString实现方式。可以看见打印对象时,会输出类名( getClass() )全限定名(.getName() )@ 哈希码( Integer.toHexString(hashCode() )

可以看见默认行为,其可读性差,仅能区分“不同对象”,无法体现对象具体数据。

2.为什么重写ToString 方法

重写后,可自定义对象的字符串格式,让打印日志输出更直观,直接体现对象的属性值,方便调试和理解对象状态。

可以看一下不重写toString时是这样:

重写之后就是这样了(上方有源代码)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92315.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92315.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

流形折叠与条件机制

1. 为什么要防止流形折叠&#xff08;mode collapse&#xff09; 流形折叠 生成器只学会输出极少数甚至单一模式&#xff08;mode&#xff09;的样本&#xff0c;而完全忽略数据分布的多样性。 后果一句话&#xff1a;“模型看起来生成了很多图&#xff0c;其实都在重复同一张…

《从零构建大语言模型》学习笔记2,文本数据处理1(以及tiktoken库无法下载gpt2参数,调用get_encoding时SSL超时的解决方法)

《从零构建大语言模型》学习笔记2&#xff0c;文本数据处理1 文章目录《从零构建大语言模型》学习笔记2&#xff0c;文本数据处理1前言1、分词2.将把提取出来的词元转换为数字ID3.添加特殊上下文标记4. 字节对编码&#xff08;以及tiktoken库无法下载gpt2参数&#xff0c;调用g…

【AI工具】解放双手,操控浏览器的工具对比,来了

&#x1f4d2;前言在github上面&#xff0c;有几个操作浏览器的mcp工具&#xff1a;browser-use / browser-usemicrosoft / playwright-mcpAgentDeskAI / browser-tools-mcphangwin / mcp-chrome想知道他们的区别吗&#xff0c;想知道那个更适合你吗&#xff0c;想。。。&#…

Linux 操作系统基础知识总结

1、操作系统总体介绍 CPU&#xff1a; 就像人的大脑&#xff0c;主要负责相关事情的判断以及实际处理的机制。 查询指令&#xff1a; cat /proc/cpuinfo 内存&#xff1a; 大脑中的记忆区块&#xff0c;将皮肤、眼睛等所收集到的信息记录起来的地方&#xff0c;以供CPU进行判断…

cudagraph 本质详解

理解 CUDA Graph 的本质,关键在于理解它解决了什么问题,以及它通过什么机制来解决这个问题。 一、 核心问题:传统 CUDA 编程的“CPU 瓶颈” 在 CUDA Graph 出现之前,我们通常使用 CUDA Stream 来向 GPU 提交任务。这是一个动态的过程: CPU 作为指挥官:CPU 循环地、逐条…

Spring MVC 父子容器深度解析:原理、实战与优化

1. 父子容器的定义与设计初衷一句话总结&#xff1a;父子容器的核心价值在于解耦 Web 层与业务层&#xff0c;实现职责分离与上下文隔离。1.1 父子容器的层次关系在 Spring MVC 中&#xff0c;容器分为两类&#xff1a;父容器&#xff08;Root ApplicationContext&#xff09;&…

AI赋能SEO关键词优化策略

内容概要 人工智能&#xff08;AI&#xff09;技术正深刻改变着搜索引擎优化&#xff08;SEO&#xff09;的实践方式&#xff0c;尤其在关键词研究这一核心领域带来了革命性的影响。本文聚焦于AI如何赋能SEO关键词优化策略&#xff0c;系统性地探讨其核心价值与应用路径。我们将…

虚拟机Ubuntu图形化界面root用户登录错误

当在 Ubuntu 图形界面登录 root 用户出现错误无法进入时 1. 检查 PAM 配置文件 PAM&#xff08;Pluggable Authentication Modules&#xff0c;可插拔认证模块&#xff09;负责管理用户认证相关的策略。图形登录界面的 PAM 配置文件通常是 /etc/pam.d/gdm-password 。以管理员权…

【杂谈】-逆缩放悖论:为何更多思考会让AI变“笨“?

逆缩放悖论&#xff1a;为何更多思考会让AI变"笨"&#xff1f; 文章目录逆缩放悖论&#xff1a;为何更多思考会让AI变"笨"&#xff1f;1、解码逆缩放现象2、AI 推理失效的五大症结3、AI 推理应对复杂度的策略图谱4、人工智能评估体系的反思5、人工智能推理…

强制用户更改WordPress密码的重要性及实现方法

确保 WordPress 网站的安全性是每位网站管理者的重要任务。在网络安全日益受到关注的今天&#xff0c;为用户提供安全、稳定的网络环境至关重要。而一个有效的方法就是强制用户定期更改密码。这篇文章将介绍为什么要强制用户更改密码以及如何在 WordPress 中实现这一功能。同时…

计算机基础速通--数据结构·串的应用

如有问题大概率是我的理解比较片面&#xff0c;欢迎评论区或者私信指正。 友友们&#xff0c;我遇到了一个大问题&#xff0c;技术类的英文面&#xff08;ai应用开发/java后端偏金融方向&#xff09;该如何准备&#xff1f;本人英语就过了个六级&#xff0c;脑阔疼额。友友们有…

05--STL认识(了解)

1. STL概念——标准模板库 STL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架。 STL与CPP标准库的关系&#xff1a; 2. STL的版本 3. STL的组成 4. STL…

VBA经典应用69例应用9:ReDim语句的语法

《VBA经典应用69例》&#xff08;版权10178981&#xff09;&#xff0c;是我推出的第九套教程&#xff0c;教程是专门针对初级、中级学员在学习VBA过程中可能遇到的案例展开&#xff0c;这套教程案例众多&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以便…

连锁店管理系统的库存跟踪功能:数字化转型下的零售运营核心

在连锁零售行业&#xff0c;库存管理的效率直接决定着运营成败。传统人工库存管理模式早已难以应对全渠道销售时代的复杂需求&#xff0c;而连锁店管理系统的库存跟踪功能&#xff0c;正成为解决库存难题、提升客户体验的关键武器。本文将深入解析施易德&#xff08;cegid&…

Nestjs框架: 接口安全与响应脱敏实践 --- 从拦截器到自定义序列化装饰器

接口安全问题&#xff1a;敏感数据脱敏的必要性 在用户注册成功后&#xff0c;若直接将用户数据&#xff08;如密码、ID 等&#xff09;返回给前端&#xff0c;存在严重的安全风险 为此&#xff0c;需要在接口响应前对数据进行脱敏处理 关键点&#xff1a; 敏感字段&#xff…

Python包与虚拟环境工具全景对比:从virtualenv到uv的演进

Python 的开发环境管理一直是综合性的工程问题。随着工具和规范的不断进化&#xff0c;我们看到了从 virtualenv / pip 开始&#xff0c;到 pipenv 和 poetry 的环境一体化&#xff0c;再到 uv 和 hatch 这样的一体化、高性能新生代工具。 本文将对比这些工具的特点、优势和选型…

期货和期权对冲后能盈利吗?

本文主要介绍期货和期权对冲后能盈利吗&#xff1f;期货和期权作为金融衍生品的两大核心工具&#xff0c;其组合对冲策略的盈利性取决于市场走势、策略设计、成本管控及风险对冲效果。对冲的本质是降低风险&#xff0c;但通过合理设计&#xff0c;部分策略可在对冲风险的同时创…

【其他分类】Showrunner AI版的Netflix 互动故事创作平台 进行动画生成与微调、角色场景创建

Showrunner是一个AI 驱动的角色场景动画。视觉风格较为统一&#xff0c;偏向 3D Q 版卡通风格&#xff0c;支持语音对白修改、镜头相机切换、动画角色和场景设置等功能。 论文原文中文翻译官方地址pdf版 、网页版pdf版https://www.showrunner.xyz/ 当前的2D 动画软件&#xff…

K8s 常见故障案例分析

#作者&#xff1a;程宏斌 文章目录一、节点故障&#xff08;一&#xff09;节点 NotReady 状态排查步骤解决方案二、Pod 故障&#xff08;一&#xff09;Pod 一直处于 Pending 状态排查步骤解决方案&#xff08;二&#xff09;Pod 频繁重启故障现象排查步骤解决方案三、控制器故…

半精度权重 及 Phi-3线性层的权重分布

半精度权重 我们可以使用张量的 to() 方法以及适当的类型 torch.float16,将权重转换为 FP16: torch.manual_seed(11) weights = torch.randn(1000) * .07 weights.min(),