一文读懂java变量类型

前言

在学习和使用Java编程语言时,理解变量类型是至关重要的基础知识。Java是一种静态类型语言,强调变量必须先声明其类型,才能进行后续操作。因此,对于初学者来说,了解Java中不同的变量类型及其特性是迈向编程成功的第一步。

本文旨在帮助大家快速、简洁地了解Java的变量类型,从而提升对编程语言的理解和应用能力。无论您是初学者还是有一定经验的开发者,我相信这篇文章将对您有所帮助。

在接下来的内容中,我将全面涵盖Java中的基本数据类型、引用数据类型以及如何声明和使用不同类型的变量。通过清晰的说明、实例代码和有趣的示意图,我将简化复杂的概念,使小伙伴们能够轻松掌握并运用Java的各种变量类型。

有哪些变量类型?

按照访问权限划分:

  • 局部变量:只在其所在的范围内有效
    1. 方法中的局部变量
  public void exampleMethod() {int num = 10; // 在方法内部声明并初始化局部变量numSystem.out.println(num); // 输出结果为10}
  1. 构造函数中的局部变量
 public class ExampleClass {public ExampleClass() {int num = 20; // 在构造函数内部声明并初始化局部变量numSystem.out.println(num); // 输出结果为20}}
  1. 代码块中的局部变量
 public void exampleMethod() {{int num = 30; // 在代码块内部声明并初始化局部变量numSystem.out.println(num); // 输出结果为30}}
  1. for循环中的局部变量
 public void exampleMethod() {for (int i = 0; i < 5; i++) {int num = i; // 在for循环内部声明并初始化局部变量numSystem.out.println(num); // 输出结果依次为0, 1, 2, 3, 4}}
  • 类变量:用关键字 static 在类中定义的变量,被所有对象共享,也称为静态变量
    1. 类方法中的类变量
 public class ExampleClass {private static int count; // 在类中声明类变量countpublic static void incrementCount() {count++; // 在类方法中使用类变量count}public static void main(String[] args) {incrementCount(); // 调用类方法修改类变量countSystem.out.println(count); // 输出结果为1}}
  1. 构造函数中的类变量
 public class ExampleClass {private static int count; // 在类中声明类变量countpublic ExampleClass() {count++; // 在构造函数中使用类变量count}public static void main(String[] args) {ExampleClass obj1 = new ExampleClass(); // 创建对象实例,调用构造函数ExampleClass obj2 = new ExampleClass(); // 创建另一个对象实例,调用构造函数System.out.println(count); // 输出结果为2,因为两次构造函数调用都修改了类变量count}}
  • 实例变量: 在类中定义的变量,每个对象都有自己的一份
    1. 在实例方法中使用实例变量
  public class ExampleClass {private int count; // 在类中声明实例变量countpublic void incrementCount() {count++; // 在实例方法中使用实例变量count}public static void main(String[] args) {ExampleClass obj = new ExampleClass(); // 创建对象实例obj.incrementCount(); // 调用实例方法修改实例变量countSystem.out.println(obj.count); // 输出结果为1,访问对象实例的实例变量count}}
  1. 构造函数中的实例变量
 public class ExampleClass {private int count; // 在类中声明实例变量countpublic ExampleClass() {count = 10; // 在构造函数中初始化实例变量count}public static void main(String[] args) {ExampleClass obj = new ExampleClass(); // 创建对象实例System.out.println(obj.count); // 输出结果为10,访问对象实例的实例变量count}}
  • 被 final 关键字 修饰的变量: 当一个变量被 final 修饰时,它表示该变量是一个常量,一旦赋值后就不能再改变 ,因此final 修饰符可以用于实例变量、局部变量和方法参数,但无法用于类(因为类无法被继承)。
    1. final实例变量
 public class ExampleClass {private final int count; // 声明一个 final 实例变量public ExampleClass() {count = 10; // 在构造函数中为 final 实例变量赋值}public static void main(String[] args) {ExampleClass obj = new ExampleClass(); // 创建对象实例// obj.count = 20; // 错误!无法修改 final 实例变量的值System.out.println(obj.count); // 输出结果为10}}
  1. final 局部变量
 public class ExampleClass {public static void main(String[] args) {final int number = 5; // 声明一个 final 局部变量// number = 10; // 错误!无法修改 final 局部变量的值System.out.println(number); // 输出结果为5}}

常规分类

  • 基本数据类型
    • 整数类型:byte、short、int、long
    • 浮点数类型:float、double
    • 字符类型:char
    • 布尔类型:boolean
  • 引用数据类型
    • 类:使用关键字 class 定义的自定义类型。
    • 接口:使用关键字 interface 定义的接口类型。
    • 数组:使用关键字 [] 创建的一组具有相同类型的数据元素。
  • 特殊类型
    • null 类型:表示变量不引用任何对象。
    • void 类型:表示方法没有返回值。

如何声明和使用

整数类型:

javaCopy Codebyte byteVariable = 127;
short shortVariable = 32767;
int intVariable = 2147483647;
long longVariable = 9223372036854775807L; // 注意:long类型的值后面需要加上"L"表示长整型System.out.println(byteVariable);
System.out.println(shortVariable);
System.out.println(intVariable);
System.out.println(longVariable);

浮点数类型:

javaCopy Codefloat floatVariable = 3.14f; // 注意:float类型的值后面需要加上"f"表示单精度浮点数
double doubleVariable = 3.1415926535;System.out.println(floatVariable);
System.out.println(doubleVariable);

字符类型:

javaCopy Codechar charVariable = 'A';
String stringVariable = "Hello";System.out.println(charVariable);
System.out.println(stringVariable);

布尔类型:

javaCopy Codeboolean booleanVariable = true;System.out.println(booleanVariable);

引用数据类型(类、接口、数组):

javaCopy Codeclass MyClass {// 类定义
}interface MyInterface {// 接口定义
}int[] intArray = {1, 2, 3, 4, 5}; // 创建一个整数类型的数组MyClass myObject = new MyClass(); // 创建一个类的实例MyInterface myInterface = new MyInterface() {// 匿名内部类实现接口
};

特殊类型:

javaCopy CodeObject nullObject = null; // null类型void myVoidMethod() {// void类型方法,无返回值
}

初始化位置、作用范围

+---------------+-------------+-------------------+-----------------+
|   变量类型     | 初始化位置   |      作用范围      |    变量类型      |
+---------------+-------------+-------------------+-----------------+
|  局部变量      | 方法、构造   |   声明所在的方法    | 基本类型或引用   |
|               | 函数或代码   |   或代码块中可见    | 类型            |
|               | 块          |                   |                 |
+---------------+-------------+-------------------+-----------------+
|  类变量        | 类中声明     | 所有方法、构造函数  | 基本类型或引用   |
|               |             | 和代码块都可访问    | 类型            |
|               |             |                   |                 |
+---------------+-------------+-------------------+-----------------+
|  final 变量   | 声明或构造    | 与上下文相关       | 基本类型或引用    |
|               | 函数中初始化  |                  | 类型             |
+---------------+-------------+-------------------+-----------------+
|  实例变量      | 类中声明     | 对象实例可访问      | 基本类型或引用   |
|               |             |                   | 类型            |
+---------------+-------------+-------------------+-----------------+

他们的相同点和不同点

相同点

  1. 声明位置:

    • 局部变量、类变量、final 修饰的变量和实例变量都是在类的内部进行声明。
    • 它们都需要指定变量的类型和名称。
  2. 访问修饰符:

    • 局部变量、类变量、final 修饰的变量和实例变量都可以使用访问修饰符来限制对其的访问(例如,public、private、protected)。
  3. 变量类型:局部变量、类变量、final 修饰的变量和实例变量可以是任何基本类型或引用类型。

    不同点

    1. 初始化位置:
      • 局部变量:在方法、构造函数或代码块中声明,并且在使用前进行初始化。
      • 类变量:在类中声明,可以在声明时初始化或在静态代码块中初始化。
      • final 修饰的变量:可以在声明时初始化或在构造函数中初始化。
      • 实例变量:在类中声明,可以在声明时初始化或在构造函数中初始化。
    2. 作用范围:
      • 局部变量:只在其所在的方法、构造函数或代码块中可见。
      • 类变量:整个类中的所有方法、构造函数和代码块都可以访问类变量。
      • final 修饰的变量:与其它变量类型类似,作用范围取决于其所在的上下文。
      • 实例变量:每个类的实例(对象)都有自己的实例变量副本,只能通过对象进行访问。

总结

局部变量、类变量、被 final 关键字修饰的变量和实例变量在初始化位置和作用范围上有所不同。

  • 它们都是在类的内部进行声明,并且可以使用访问修饰符来限制对其的访问。

  • 变量类型可以是任何基本类型或引用类型。

    变量之间的 持久性和作用范围的 大小关系(final可以是局部变量、实例变量或类变量 这里不做比较)

在这里插入图片描述

按作用范围从小到大排序,可以按照以下顺序:

  1. 局部变量:局部变量的作用范围限制在声明它的方法、构造函数或代码块内部。它们只能在声明所在的范围内使用,超出范围后就无法访问。
  2. 实例变量:实例变量是定义在类中、方法之外的变量。每个类的实例都拥有自己的实例变量副本,在整个类的所有成员方法中都可以访问和修改这些变量。
  3. 类变量(静态变量):类变量属于整个类而不是特定的实例。它们在类加载时被初始化,并且在整个类的所有实例之间共享相同的值。类变量可以通过类名直接访问。

按持久性从小到大分类变量可以按照以下顺序:

  1. 局部变量:局部变量的生命周期仅限于包含它们的方法、构造函数或代码块的执行过程。当方法执行完毕或代码块结束时,局部变量将被销毁。
  2. 实例变量:实例变量属于类的实例,并且在创建对象时被初始化。它们在对象被销毁之前一直存在,即对象存在,实例变量也存在。
  3. 类变量(静态变量):类变量属于整个类而不是特定的实例。它们在类加载时被初始化,且在整个程序运行期间都存在。即使没有创建类的实例,类变量也可以被访问。

与线程安全相关知识点

  • static 变量
    当多个线程同时访问和修改类变量时,可能会出现以下线程安全问题:

    1. 竞态条件(Race Condition):如果多个线程同时对类变量进行写操作或读写操作,可能导致不可预测的结果。例如,一个线程正在修改类变量的值,而另一个线程同时在读取该变量的值,可能导致读取到不一致或过时的数据。
    2. 内存可见性问题(Visibility Problem):当一个线程修改了类变量的值后,其他线程可能无法立即感知到这个变化。这是因为每个线程都有自己的工作内存,它们可能将类变量的副本保存在各自的工作内存中。因此,其他线程可能仍然访问的是旧值。
    3. 并发更新问题(Concurrent Update Problem):当多个线程同时对类变量进行修改时,可能会导致数据不一致性。例如,多个线程同时递增一个类变量的值,最终结果可能不符合预期。
      如图所示:
      在这里插入图片描述

    要解决类变量的线程安全问题,可以采取以下措施:

    1. 使用同步机制:通过使用关键字 synchronized 或使用锁(如 ReentrantLock)来保证同一时间只有一个线程能够访问类变量,从而避免竞态条件和内存可见性问题。
    2. 使用原子操作:可以使用原子类(如 AtomicInteger)来执行对类变量的原子操作,保证线程安全。
    3. 避免共享:如果类变量不需要共享,并且每个线程都需要拥有自己的副本,可以将类变量声明为局部变量或实例变量,以避免线程安全问题。
      需要根据具体情况选择适当的线程安全措施,并在设计和编写代码时考虑到多线程环境下的并发访问问题。
  • 局部变量

在局部变量中引用了一个对象,且该对象本身存在线程安全问题,那么在访问该对象时仍然需要采取适当的同步措施,以避免线程安全问题的发生。

例如:引入形参或者有返回值的情况下就会有线程安全问题
解决方法与上面类似,需要采取适当的同步机制。


相信有一定基础的小伙伴已经发现了,final关键字修饰的变量可以是 : 成员变量 类变量 局部变量
不过作者认为final关键字修饰的变量比较特殊,就拿出来和其他变量一起介绍啦。

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

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

相关文章

创建vue3项目并引用elementui

1.创建vu3项目&#xff1a; vue3官网&#xff1a;简介 | Vue.js 执行命令 npm create vuelatest 2.终端会出现如下选项&#xff0c;不确定的直接enter键进入下一步&#xff1b; 3.然后再执行下方命令&#xff1a; cd <your-project-name> npm install4.安装依赖成功…

Java的XWPFTemplate工具类导出word.docx的使用

依赖 <!-- word导出 --><dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.7.3</version></dependency><!-- 上面需要的依赖--><dependency><groupId>org.ap…

phpcmsV9.6.0sql注入漏洞分析

目录 前言 环境准备 漏洞点 看一看parse_str函数 看一看sys_auth函数 看一看get_one函数 全局搜索sys_auth($a_k, ENCODE) 查看哪里调用了 set_cookie 查看safe_replace函数 判断登录绕过 index的业务 加载modules/wap/index.php 加载modules/attachment/attachme…

AI性能指标解析:误触率与错误率

简介&#xff1a;随着人工智能&#xff08;AI&#xff09;技术的不断发展&#xff0c;它越来越多地渗透到我们日常生活的各个方面。从个人助手到自动驾驶&#xff0c;从语音识别到图像识别&#xff0c;AI正不断地改变我们与世界的互动方式。但你有没有想过&#xff0c;如何准确…

【漏洞复现】广联达办公OAsql+文件上传+弱口令

漏洞描述 广联达办公OA是一款综合办公自动化解决方案,旨在提高组织内部的工作效率和协作能力。它提供了一系列功能和工具,帮助企业管理和处理日常办公任务、流程和文档。默认弱口令admin password,后面就不提了。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当…

YOLOv5算法改进(16)— 增加小目标检测层

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。小目标检测层是指在目标检测任务中用于检测小尺寸目标的特定网络层。由于小目标具有较小的尺寸和低分辨率&#xff0c;它们往往更加难以检测和定位。YOLOv5算法的检测速度与精度较为平衡&#xff0c;但是对于小目标的检测效…

使用qt5.6.3的注意事项:

1 当SQL模型(如QSqlTableModel)使用一个无效的索引时,应用程序有可能崩溃。 无效索引的原因有:1. 索引列包含NULL值:如果索引中的某列允许NULL,而查询使用此列进行过滤但未考虑NULL值,则索引变得无效。2. 索引失效:索引列的数据发生变化,但索引未及时更新,导致索引与数据不一致…

如何进行机器学习

进行机器学习主要包含以下步骤&#xff1a; 获取数据&#xff1a;首先需要获取用于学习的数据&#xff0c;数据的质量和数量都会影响机器学习的效果。如果自己的数据量较少&#xff0c;可以尝试在网上寻找公开数据集进行训练&#xff0c;然后使用自己的数据进行微调。另一种方…

构建企业分支网络

构建企业分支网络 目录 1.1 项目背景 1.2 项目拓扑 1.3 项目需求 1.4 设备选型 1.5 技术选型 1.6 地址规划 1.6.1 交换设备地址规划表 1.6.2 路由设备地址规划表 1.6.3 ISP设备地址规划表 1.6.4 终端地址规划表 1.6.4.1 VLAN 规划 1.7 VLAN 规划 1.8 项目实施 1.…

kafka位移提交

目录 前言&#xff1a; 位移提交&#xff1a; 小结&#xff1a; 参考资料 前言&#xff1a; Consumer 需要向 Kafka 汇报自己的位移数据&#xff0c;这个汇报过程被称为提交位移&#xff08;Committing Offsets&#xff09;。因为 Consumer 能够同时消费多个分区的数据&a…

如何写http mjpeg server

目的 是为了让unity ue 等三维引擎直接读取mjpeg图像进行纹理贴图 使用qt&#xff0c;opencv等等&#xff0c;因为经常要进行图像处理 opencv 使用opencv 和QImage 来转换图像 QImage Widget::Mat2QImage(cv::Mat const& src) { cv::Mat temp; // make the same cv:…

时序分解 | MATLAB实现RIME-VMD霜冰优化算法优化VMD变分模态分解信号分量可视化

时序分解 | MATLAB实现RIME-VMD霜冰优化算法优化VMD变分模态分解信号分量可视化 目录 时序分解 | MATLAB实现RIME-VMD霜冰优化算法优化VMD变分模态分解信号分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 RIME-VMD【23年新算法】霜冰优化算法优化VMD变分模态分…

TinTin Web3 动态精选:以太坊基金会推出 EELS、Arbitrum Stylus 上线

TinTin 快讯由 TinTinLand 开发者技术社区打造&#xff0c;旨在为开发者提供最新的 Web3 新闻、市场时讯和技术更新。TinTin 快讯将以周为单位&#xff0c; 汇集当周内的行业热点并以快讯的形式排列成文。掌握一手的技术资讯和市场动态&#xff0c;将有助于 TinTinLand 社区的开…

QML、C++ 和 JS 三者之间的交互

QML、C++ 和 JS 三者之间的交互是 Qt Quick 应用开发的核心。以下是它们之间交互的常见方式: 从 QML 调用 C++ 函数要从 QML 调用 C++ 函数,您可以使用 Qt 的 QML 注册机制,例如 qmlRegisterType,将 C++ 类注册为 QML 类型。 C++ 代码: #include <QGuiApplication>…

docker push image harbor http 镜像

前言 搭建的 harbor 仓库为 http 协议&#xff0c;在本地登录后&#xff0c;推送镜像发生如下报错&#xff1a; docker push 192.168.xx.xx/test/grafana:v10.1.1 The push refers to repository [192.168.xx.xx/test/grafana] Get "https://192.168.xx.xx/v2/": dia…

LeetCode 之 二分查找

网址&#xff1a; LeetCode 704.二分查找 算法模拟&#xff1a; Algorithm Visualizer 在线工具&#xff1a; C 在线工具 如果习惯性使用Visual Studio Code进行编译运行&#xff0c;需要C11特性的支持&#xff0c;可参考博客&#xff1a; VisualStudio Code 支持C11插件配…

如何获得一个Oracle 23c免费开发者版

获取23c开发者版 简单介绍可参考这里。 获取数据库可以参考这篇文章Introducing Oracle Database 23c Free – Developer Release或这里。 Docker Image 这是最快的方法。在OCI上创建一个计算实例&#xff0c;然后就可以拉取image使用了。 docker的安装和配置不赘述了。 …

html实现邮件模版布局-flex布局table布局-demo

邮件模版布局 flex - 布局简单方便 兼容性差 table - 优点 就是兼容性好&#xff0c;其他没有优点 注&#xff1a;使用图片需要png最好&#xff0c;使用svg图google邮箱会出现不能使用的情况 效果图 flex布局 <!DOCTYPE html> <html lang"en" xmlns:th&qu…

sql server事务隔离别 、 mysql 事务隔离级别、并发性问题

隔离级别和锁 SQL中 mysql 、Oracle 、sql server 等数据库 都是客户端和服务器架构的软件&#xff0c;对于同一个服务器来说&#xff0c;可以有若干个客户端与之连接&#xff0c;每个客户端与服务器连接上之后&#xff0c;就可以称为一个 【会话&#xff08;session&#xff0…

Linkstech多核并行仿真丨光伏发电系统模型及IEEE 39 bus模型多核并行实测

新能源场站和区域电网作为复杂且具有动态特性的大规模电力系统&#xff0c;需要实时仿真测试来验证其性能、稳定性和响应能力。在这种背景下&#xff0c;多核并行仿真运算显得尤为重要。多核并行仿真能够同时处理电力系统的复杂模型&#xff0c;加速仿真过程&#xff0c;实现接…