Java基础:面向对象编程3
1 Java可变长参数
1.1 概述
Java 的可变长参数(Varargs)是在 Java 1.5 中引入的功能,允许方法接受任意数量的相同类型的参数。可变参数的语法是在参数类型后面加上三个点(...),例如 int... numbers。
1.2 使用规则
- 可变参数必须放在参数列表的最后一位:如果方法有多个参数,可变参数必须放在最后。例如:
public void printNumbers(String prefix, int... numbers) {// 方法体 } - 只能有一个可变参数:一个方法中只能有一个可变参数。
1.3 原理
当使用可变参数时,Java 会在编译时创建一个数组,数组的大小就是传入的可变参数的数量。然后将这些参数放入数组中,并将数组传递给方法。
例如:
public void printNumbers(int... numbers) {for (int number : numbers) {System.out.println(number);}
}
调用 printNumbers(1, 2, 3) 时,Java 会创建一个 int[] 数组 {1, 2, 3},然后传递给方法。
1.4 使用场景
可变参数通常用于需要处理任意数量相同类型对象的场景。例如:
- 打印任意数量的整数
- 计算任意数量的数字的和
- 处理任意数量的字符串
1.5 注意事项
-
避免重载带有可变参数的方法:重载带有可变参数的方法可能会导致编译器无法确定调用哪个方法,从而引发编译错误。例如:
public void print(String... args) {// 方法体 }public void print(String arg1, String... args) {// 方法体 }调用
print("a")时,编译器无法确定是调用第一个方法还是第二个方法。 -
明确指示:如果必须重载带有可变参数的方法,确保在调用时明确指示参数,避免编译器混淆。
1.6 示例代码
public class VarargsExample {public static void main(String[] args) {printNumbers(1, 2, 3);printNumbers(4, 5);printNumbers();}public static void printNumbers(int... numbers) {for (int number : numbers) {System.out.println(number);}}
}
2 Java native方法
2.1 概念
本地方法(Native Method)是用 native 关键字修饰的方法,通常不需要用 Java 语言实现。本地方法允许 Java 代码调用其他语言(如 C/C++)编写的代码。
2.2 JNI:Java Native Interface
JNI(Java Native Interface)是 Java 平台的一部分,从 Java 1.1 开始引入,允许 Java 代码与其他语言编写的代码进行交互。JNI 主要用于以下场景:
- 标准 Java 类库不支持的功能
- 调用已有的 C/C++ 库
- 提高性能,特别是在需要接近硬件或运行次数特别多的方法中
2.2.1 JNI 的优点
- 扩展 Java 功能:可以通过 JNI 调用其他语言编写的库。
- 性能优化:在某些情况下,使用本地代码可以提高性能。
2.2.2 JNI 的缺点
- 跨平台性丧失:本地代码通常不跨平台,需要在不同系统环境下重新编译。
- 安全性降低:本地代码的不当使用可能导致程序崩溃。
2.3 用 C 语言编写本地方法
2.3.1 步骤
- 编写带有 native 方法的 Java 类,生成
.java文件。 - 编译 Java 类,生成
.class文件。 - 生成头文件:使用
javah -jni或javac -h生成.h文件。 - 实现本地方法:使用 C/C++ 实现
.h文件中的方法,生成.c或.cpp文件。 - 生成动态链接库:将 C/C++ 编写的文件生成动态链接库(如
.dll或.so)。
2.3.2 示例:HelloWorld 程序
-
编写 Java 类:
public class HelloJNI {static {System.loadLibrary("hello"); // 加载动态链接库}public native void sayHello(); // 声明本地方法public static void main(String[] args) {new HelloJNI().sayHello(); // 调用本地方法} } -
编译 Java 类:
javac HelloJNI.java -
生成头文件:
javac -h . HelloJNI.java这将生成
HelloJNI.h文件。 -
实现本地方法:
#include <jni.h> #include "HelloJNI.h" #include <stdio.h>JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject obj) {printf("Hello, JNI!\n"); } -
编写编译脚本:
# compile.sh gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin" -dynamiclib -o libhello.dylib HelloJNI.c -
执行脚本:
sh compile.sh -
运行 Java 程序:
java HelloJNI
2.4 JNI 调用 C 的流程图
Java 代码 -> JNI 接口 -> 本地代码 (C/C++)

2.5 native 关键字
-
native 用于修饰方法,表示该方法的实现在外部定义,通常用 C/C++ 实现。
-
语法:
- 修饰方法的位置必须在返回类型之前。
- 不能用
abstract修饰,没有方法体。 - 返回值可以是任意类型。
-
native 方法示例
public native void sayHello();
2.6 小结
- JNI 允许 Java 代码与其他语言编写的代码进行交互,扩展了 Java 的功能。
- 本地方法 用
native关键字修饰,通常用于调用 C/C++ 库或提高性能。 - 注意事项:使用 JNI 会丧失跨平台性,且本地代码的不当使用可能导致程序崩溃。
3 Java构造方法
3.1 概念
构造方法(Constructor)是 Java 中的一种特殊方法,用于在创建对象时初始化对象的状态。每次使用 new 关键字创建对象时,构造方法至少会被调用一次。如果没有显式定义构造方法,编译器会提供一个默认的无参构造方法。
3.2 创建构造方法的规则
- 名称与类名相同:构造方法的名称必须与类名完全一致。
- 无返回类型:构造方法没有返回类型,包括
void。 - 不能是抽象的、静态的、最终的、同步的:
- 抽象:构造方法不能被子类继承,因此用
abstract修饰没有意义。 - 静态:构造方法用于初始化对象,因此用
static修饰没有意义。 - 最终:构造方法不能被子类继承,因此用
final修饰没有意义。 - 同步:多个线程不会同时创建内存地址相同的同一个对象,因此用
synchronized修饰没有必要。
- 抽象:构造方法不能被子类继承,因此用
3.3 语法格式
class class_name {public class_name(){} // 默认无参构造方法public ciass_name([paramList]){} // 定义有参数列表的构造方法…// 类主体
}
3.4 默认构造方法
- 无参构造方法:如果构造方法没有任何参数,它就是一个无参构造方法。
- 默认构造方法:如果类中没有显式定义构造方法,编译器会自动提供一个无参构造方法。
- 目的:主要为对象的字段提供默认值。
- 代码示例
public class DefaultConstructorExample {private int value;// 编译器提供的默认构造方法public DefaultConstructorExample() {this.value = 0; // 默认值}public static void main(String[] args) {DefaultConstructorExample obj = new DefaultConstructorExample();System.out.println(obj.value); // 输出: 0}
}
3.5 有参构造方法
- 有参数的构造方法:可以有一个或多个参数,用于为不同的对象提供不同的初始值。
- 替代方案:如果没有有参构造方法,可以通过
setter方法为字段赋值。 - 代码示例
public class ParameterizedConstructorExample {private String name;public ParameterizedConstructorExample(String name) {this.name = name;}public static void main(String[] args) {ParameterizedConstructorExample obj = new ParameterizedConstructorExample("Java");System.out.println(obj.name); // 输出: Java}
}
3.6 重载构造方法
- 构造方法重载:通过提供不同的参数列表来重载构造方法。编译器会根据参数的数量和类型来决定调用哪一个构造方法。
- 代码示例
public class OverloadedConstructorExample {private int id;private String name;public OverloadedConstructorExample(int id) {this.id = id;}public OverloadedConstructorExample(int id, String name) {this.id = id;this.name = name;}public static void main(String[] args) {OverloadedConstructorExample obj1 = new OverloadedConstructorExample(1);OverloadedConstructorExample obj2 = new OverloadedConstructorExample(2, "Java");System.out.println(obj1.id); // 输出: 1System.out.println(obj2.id + " " + obj2.name); // 输出: 2 Java}
}
3.7 构造方法和方法的区别
| 特性 | 方法 | 构造方法 |
|---|---|---|
| 目的 | 反映对象的行为 | 初始化对象的字段 |
| 返回类型 | 可以有返回类型 | 没有返回类型 |
| 调用方式 | 明确的,开发者通过代码决定调用 | 隐式的,通过编译器完成 |
| 编译器提供 | 不会由编译器提供 | 如果没有明确提供无参构造方法,编译器会提供 |
| 名称 | 可以和类名相同,也可以不同 | 必须和类名相同 |
3.8 复制对象
复制一个对象可以通过以下三种方式完成:
- 通过构造方法:使用另一个对象作为参数来创建新对象。
- 通过对象的值:手动复制对象的每个字段。
- 通过
Object类的clone()方法:实现Cloneable接口并重写clone()方法。
- 通过构造方法
public class CopyConstrutorPerson {private String name;private int age;public CopyConstrutorPerson(String name, int age) {this.name = name;this.age = age;}public CopyConstrutorPerson(CopyConstrutorPerson person) {this.name = person.name;this.age = person.age;}public void out() {System.out.println("姓名 " + name + " 年龄 " + age);}public static void main(String[] args) {CopyConstrutorPerson p1 = new CopyConstrutorPerson("沉默王二",18);p1.out();CopyConstrutorPerson p2 = new CopyConstrutorPerson(p1);p2.out();}
}
在上面的例子中,有一个参数为 CopyConstrutorPerson 的构造方法,可以把该参数的字段直接复制到新的对象中,这样的话,就可以在 new 关键字创建新对象的时候把之前的 p1 对象传递过去。
- 通过对象的值
public class CopyValuePerson {private String name;private int age;public CopyValuePerson(String name, int age) {this.name = name;this.age = age;}public CopyValuePerson() {}public void out() {System.out.println("姓名 " + name + " 年龄 " + age);}public static void main(String[] args) {CopyValuePerson p1 = new CopyValuePerson("沉默王二",18);p1.out();CopyValuePerson p2 = new CopyValuePerson();p2.name = p1.name;p2.age = p1.age;p2.out();}
}
直接拿 p1 的字段值复制给 p2 对象(p2.name = p1.name)
- 通过
Object类的clone()方法
public class ClonePerson implements Cloneable {private String name;private int age;public ClonePerson(String name, int age) {this.name = name;this.age = age;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public void out() {System.out.println("姓名 " + name + " 年龄 " + age);}public static void main(String[] args) throws CloneNotSupportedException {ClonePerson p1 = new ClonePerson("沉默王二",18);p1.out();ClonePerson p2 = (ClonePerson) p1.clone();p2.out();}
}
通过 clone() 方法复制对象的时候,ClonePerson 必须先实现 Cloneable 接口的 clone() 方法,然后再调用clone()方法(ClonePerson p2 = (ClonePerson) p1.clone())。
3.9 小结
- 构造方法虽然没有返回值,但返回的是类的对象。
- 初始化字段只是构造方法的一种工作,它还可以做更多,比如启动线程、调用其他方法等。
4 思维导图



参考链接
-
Java可变参数详解,5分钟教会我妹
-
手把手教你用 C语言实现 Java native 本地方法
-
Java构造方法:打开Java对象创建之门的钥匙
相关文章:
Java基础:面向对象编程3
1 Java可变长参数 1.1 概述 Java 的可变长参数(Varargs)是在 Java 1.5 中引入的功能,允许方法接受任意数量的相同类型的参数。可变参数的语法是在参数类型后面加上三个点(...),例如 int... numbers。 1.…...
实验kubernetes的CPU绑定策略
CPU 管理配置 CPU 管理策略通过 kubelet 参数 --cpu-manager-policy 或 KubeletConfiguration 中的 cpuManagerPolicy 字段来指定。 支持两种策略: none:默认策略。static:允许为节点上具有某些资源特征的 Pod 赋予增强的 CPU 亲和性和独占…...
Zsh 安装与配置
目录 1 环境配置 1.1 基本工具安装 1.2 安装 oh-my-zsh 1.3 从.bashrc中迁移配置(可选) 2 主题配置 2.1 内置主题 2.2 自定义主题 2.2.1 推荐主题 3 插件安装 3.1 推荐插件 3.1.1 zsh -autosuggestions 3.1.2 zsh-syntax-highlighting 3.2 启…...
Redis可视化工具Redis Desktop Manager(附安装包)
前言 redis工具,我相信每个开发都需要,如果每次查都去client执行指令,我怕查完之后,老大就要发版咯。我之前一直用的Redis可视化工具RedisDesktopManager,总觉得差点意思,直到同事推荐了个新的,…...
sql server删除过期备份文件脚本
一、通过脚本查看过期文件,时间可以自己设定 for /f "delims" %i in (dir /b /a-d "E:\mybak_file\*.bak" ^| findstr /i "backup" ^| findstr /v /i "no_backup") do if "%~ti" LSS "2024/09/29 16:50&qu…...
【Docker系列】Docker查看镜像架构
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
Python案例 | 测试网络的下载速度上传速度和 ping 延迟
使用了 speedtest 库来测试网络的下载速度上传速度和 ping 延迟 注意,这里需要先卸载speedtest,再安装speedtest-cli pip uninstall speedtest pip install speedtest-cli其次运行代码: # 使用了 speedtest 库来测试网络的下载速度上传速度…...
一键找回,2024四大固态硬盘数据恢复工具推荐!
虽然固态硬盘(SSD)因其读写速度快、功耗低等特点受到广泛欢迎,但它并非无懈可击,数据丢失的问题依然存在。如果你也遇到了固态硬盘数据丢失的问题,那么一下的这几款软件可以一试! 福昕数据恢复 直达链接&…...
数据结构~AVL树
文章目录 一、AVL树的概念二、AVL树的定义三、AVL树的插入四、AVL树的平衡五、AVL树的验证六、AVL树的删除七、完整代码八、总结 一、AVL树的概念 AVL树是最先发明的自平衡二叉查找树,AVL是⼀颗空树,或者具备下列性质的二叉搜索树:它的左右子…...
ffmpeg面向对象——rtsp拉流探索(1)
目录 0.avformat_open_input的rtsp流程程纯净版1.rtsp拉流流程图2.rtsp拉流对象图 标准rtsp协议的基石是tcp,本节探索下ffmpeg的rtsp拉流协议tcp的创建及rtsp协商过程。 0.avformat_open_input的rtsp流程程纯净版 ffmpeg拉流,从avformat_open_input接口…...
【启明智显分享】ZX7981PM WIFI6 5G-CPE:2.5G WAN口,2.4G/5G双频段自动调速
昨天,我们向大家展现了ZX7981PG WIFI6 5G-CPE,它强大的性能也引起了一波关注,与此同时,我们了解到部分用户对更高容量与更高速网口的需求。没关系!启明智显早就预料到了!ZX7981PM满足你的需求! …...
openresty“热部署“lua
一、前言 频繁reload 或者restart影响测试使用nginx,修改lua脚本后要实际查看效果值,使用关闭lua代码缓存,可以实现实时查看代码效果。 每次请求都会从磁盘中加载lua脚本,生产上面不要开启,影响响应速度 二、修改ngin…...
基于SpringBoot+Vue+MySQL的企业招聘管理系统
系统展示 用户前台界面 管理员后台界面 企业后台界面 系统背景 在当今数字化转型的大潮中,企业对于高效、智能化的人力资源管理系统的需求日益增长。招聘作为人力资源管理的首要环节,其效率与效果直接影响到企业的人才储备与竞争力。传统的招聘方式不仅耗…...
vue3之defineComponent
defineComponent 是 Vue 3 中提供的一个辅助函数,用于定义组件。它可以帮助你更好地利用 TypeScript 的类型推断和 IDE 的自动补全功能。defineComponent 主要用于组合式 API(Composition API)和单文件组件(SFC)。 使…...
springboot+vue家政服务管理平台
作者:计算机学长阿伟 开发技术:SpringBoot、SSM、Vue、MySQL、ElementUI等,“文末源码”。 系统展示 【2024最新】基于JavaSpringBootVueMySQL的,前后端分离。 开发语言:Java数据库:MySQL技术:…...
python pip安装requirements.txt依赖与国内镜像
python pip安装requirements.txt依赖与国内镜像 如果网络通畅,直接pip安装依赖: pip install -r requirements.txt 如果需要国内的镜像,可以考虑使用阿里的,在后面加上: -i http://mirrors.aliyun.com/pypi/simple --…...
解决Qt的QWidget设计师编辑UI后和软件运行显示不一致
解决方法,只需要在main.cpp中加入下面一段代码 if (QT_VERSION > QT_VERSION_CHECK(5, 6, 0))QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling,true); 完整的代码如下 int main(int argc, char *argv[]) { if (QT_VERSION > QT_VERSION_C…...
交易所开发:构建安全、高效、可靠的数字资产交易平台
数字资产交易平台是加密市场中连接用户与数字货币的重要枢纽。开发一个安全、高效、可靠的交易所,不仅需要综合考虑技术架构、安全策略、用户体验等方面,还需严格遵循法规要求以确保合规性。本文总结了交易所开发的关键要素,包括其类型、核心…...
【Next.js 入门教程系列】09-优化技巧
原文链接 CSDN 的排版/样式可能有问题,去我的博客查看原文系列吧,觉得有用的话, 给我的库点个star,关注一下吧 上一篇【Next.js 入门教程系列】08-发送邮件 优化技巧 本篇包括以下内容: Optimizing imagesUsing third-party JS…...
Windows 11 开发详解:工具与高级用法
1. 引言 Windows 11 是微软最新的操作系统,它不仅带来了全新的用户界面和设计理念,还为开发者提供了强大的开发工具和平台支持。在过去的几年中,开发工具和技术栈发生了巨大的变化,Windows 11 通过其集成的开发环境、虚拟化技术、…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
