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

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 步骤

  1. 编写带有 native 方法的 Java 类,生成 .java 文件。
  2. 编译 Java 类,生成 .class 文件。
  3. 生成头文件:使用 javah -jnijavac -h 生成 .h 文件。
  4. 实现本地方法:使用 C/C++ 实现 .h 文件中的方法,生成 .c.cpp 文件。
  5. 生成动态链接库:将 C/C++ 编写的文件生成动态链接库(如 .dll.so)。

2.3.2 示例:HelloWorld 程序

  1. 编写 Java 类

    public class HelloJNI {static {System.loadLibrary("hello"); // 加载动态链接库}public native void sayHello(); // 声明本地方法public static void main(String[] args) {new HelloJNI().sayHello(); // 调用本地方法}
    }
    
  2. 编译 Java 类

    javac HelloJNI.java
    
  3. 生成头文件

    javac -h . HelloJNI.java
    

    这将生成 HelloJNI.h 文件。

  4. 实现本地方法

    #include <jni.h>
    #include "HelloJNI.h"
    #include <stdio.h>JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject obj) {printf("Hello, JNI!\n");
    }
    
  5. 编写编译脚本

    # compile.sh
    gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin" -dynamiclib -o libhello.dylib HelloJNI.c
    
  6. 执行脚本

    sh compile.sh
    
  7. 运行 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 复制对象

复制一个对象可以通过以下三种方式完成:

  1. 通过构造方法:使用另一个对象作为参数来创建新对象。
  2. 通过对象的值:手动复制对象的每个字段。
  3. 通过 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 思维导图

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

参考链接

  1. Java可变参数详解,5分钟教会我妹

  2. 手把手教你用 C语言实现 Java native 本地方法

  3. Java构造方法:打开Java对象创建之门的钥匙

相关文章:

Java基础:面向对象编程3

1 Java可变长参数 1.1 概述 Java 的可变长参数&#xff08;Varargs&#xff09;是在 Java 1.5 中引入的功能&#xff0c;允许方法接受任意数量的相同类型的参数。可变参数的语法是在参数类型后面加上三个点&#xff08;...&#xff09;&#xff0c;例如 int... numbers。 1.…...

实验kubernetes的CPU绑定策略

CPU 管理配置 CPU 管理策略通过 kubelet 参数 --cpu-manager-policy 或 KubeletConfiguration 中的 cpuManagerPolicy 字段来指定。 支持两种策略&#xff1a; none&#xff1a;默认策略。static&#xff1a;允许为节点上具有某些资源特征的 Pod 赋予增强的 CPU 亲和性和独占…...

Zsh 安装与配置

目录 1 环境配置 1.1 基本工具安装 1.2 安装 oh-my-zsh 1.3 从.bashrc中迁移配置&#xff08;可选&#xff09; 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工具&#xff0c;我相信每个开发都需要&#xff0c;如果每次查都去client执行指令&#xff0c;我怕查完之后&#xff0c;老大就要发版咯。我之前一直用的Redis可视化工具RedisDesktopManager&#xff0c;总觉得差点意思&#xff0c;直到同事推荐了个新的&#xff0c…...

sql server删除过期备份文件脚本

一、通过脚本查看过期文件&#xff0c;时间可以自己设定 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查看镜像架构

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

Python案例 | 测试网络的下载速度上传速度和 ping 延迟

使用了 speedtest 库来测试网络的下载速度上传速度和 ping 延迟 注意&#xff0c;这里需要先卸载speedtest&#xff0c;再安装speedtest-cli pip uninstall speedtest pip install speedtest-cli其次运行代码&#xff1a; # 使用了 speedtest 库来测试网络的下载速度上传速度…...

一键找回,2024四大固态硬盘数据恢复工具推荐!

虽然固态硬盘&#xff08;SSD&#xff09;因其读写速度快、功耗低等特点受到广泛欢迎&#xff0c;但它并非无懈可击&#xff0c;数据丢失的问题依然存在。如果你也遇到了固态硬盘数据丢失的问题&#xff0c;那么一下的这几款软件可以一试&#xff01; 福昕数据恢复 直达链接&…...

数据结构~AVL树

文章目录 一、AVL树的概念二、AVL树的定义三、AVL树的插入四、AVL树的平衡五、AVL树的验证六、AVL树的删除七、完整代码八、总结 一、AVL树的概念 AVL树是最先发明的自平衡二叉查找树&#xff0c;AVL是⼀颗空树&#xff0c;或者具备下列性质的二叉搜索树&#xff1a;它的左右子…...

ffmpeg面向对象——rtsp拉流探索(1)

目录 0.avformat_open_input的rtsp流程程纯净版1.rtsp拉流流程图2.rtsp拉流对象图 标准rtsp协议的基石是tcp&#xff0c;本节探索下ffmpeg的rtsp拉流协议tcp的创建及rtsp协商过程。 0.avformat_open_input的rtsp流程程纯净版 ffmpeg拉流&#xff0c;从avformat_open_input接口…...

【启明智显分享】ZX7981PM WIFI6 5G-CPE:2.5G WAN口,2.4G/5G双频段自动调速

昨天&#xff0c;我们向大家展现了ZX7981PG WIFI6 5G-CPE&#xff0c;它强大的性能也引起了一波关注&#xff0c;与此同时&#xff0c;我们了解到部分用户对更高容量与更高速网口的需求。没关系&#xff01;启明智显早就预料到了&#xff01;ZX7981PM满足你的需求&#xff01; …...

openresty“热部署“lua

一、前言 频繁reload 或者restart影响测试使用nginx&#xff0c;修改lua脚本后要实际查看效果值&#xff0c;使用关闭lua代码缓存&#xff0c;可以实现实时查看代码效果。 每次请求都会从磁盘中加载lua脚本&#xff0c;生产上面不要开启&#xff0c;影响响应速度 二、修改ngin…...

基于SpringBoot+Vue+MySQL的企业招聘管理系统

系统展示 用户前台界面 管理员后台界面 企业后台界面 系统背景 在当今数字化转型的大潮中&#xff0c;企业对于高效、智能化的人力资源管理系统的需求日益增长。招聘作为人力资源管理的首要环节&#xff0c;其效率与效果直接影响到企业的人才储备与竞争力。传统的招聘方式不仅耗…...

vue3之defineComponent

defineComponent 是 Vue 3 中提供的一个辅助函数&#xff0c;用于定义组件。它可以帮助你更好地利用 TypeScript 的类型推断和 IDE 的自动补全功能。defineComponent 主要用于组合式 API&#xff08;Composition API&#xff09;和单文件组件&#xff08;SFC&#xff09;。 使…...

springboot+vue家政服务管理平台

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 系统展示 【2024最新】基于JavaSpringBootVueMySQL的&#xff0c;前后端分离。 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;…...

python pip安装requirements.txt依赖与国内镜像

python pip安装requirements.txt依赖与国内镜像 如果网络通畅&#xff0c;直接pip安装依赖&#xff1a; pip install -r requirements.txt 如果需要国内的镜像&#xff0c;可以考虑使用阿里的&#xff0c;在后面加上&#xff1a; -i http://mirrors.aliyun.com/pypi/simple --…...

解决Qt的QWidget设计师编辑UI后和软件运行显示不一致

解决方法&#xff0c;只需要在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…...

交易所开发:构建安全、高效、可靠的数字资产交易平台

数字资产交易平台是加密市场中连接用户与数字货币的重要枢纽。开发一个安全、高效、可靠的交易所&#xff0c;不仅需要综合考虑技术架构、安全策略、用户体验等方面&#xff0c;还需严格遵循法规要求以确保合规性。本文总结了交易所开发的关键要素&#xff0c;包括其类型、核心…...

【Next.js 入门教程系列】09-优化技巧

原文链接 CSDN 的排版/样式可能有问题&#xff0c;去我的博客查看原文系列吧&#xff0c;觉得有用的话&#xff0c; 给我的库点个star&#xff0c;关注一下吧 上一篇【Next.js 入门教程系列】08-发送邮件 优化技巧 本篇包括以下内容: Optimizing imagesUsing third-party JS…...

Windows 11 开发详解:工具与高级用法

1. 引言 Windows 11 是微软最新的操作系统&#xff0c;它不仅带来了全新的用户界面和设计理念&#xff0c;还为开发者提供了强大的开发工具和平台支持。在过去的几年中&#xff0c;开发工具和技术栈发生了巨大的变化&#xff0c;Windows 11 通过其集成的开发环境、虚拟化技术、…...

leetcode 292.Nim游戏

思路&#xff1a;数学 这有一点博弈论的味道&#xff0c;但是我们依然可以用数学的角度去思考。 我们的入手点在这里&#xff1a; 我们是先手的前提下&#xff0c;一共有4个石头&#xff0c;但是每个人只能一次拿其中的1-3个。在一共有4个石头的情况下&#xff0c;我们无论拿…...

《最优化方法》

课件是学习的核心内容 这门课&#xff0c;作业自己交&#xff0c;但是老师不做记录&#xff0c;上课不点名&#xff0c; 不记录平时成绩。 第一章 最优化问题的概述 1.1 概述&#xff08;和考试内容无关&#xff0c;了解内容&#xff09; 例题1.1.1运输问题 数学模型&#x…...

fork中的死锁问题

背景 当我们通过fork去创建子进程时&#xff0c;当父/子进程都涉及到锁的操作&#xff0c;可能会产生死锁。 代码样例 #include <iostream> #include <mutex> #include <unistd.h> std::mutex m; int main() {std::cout << "main process begi…...

Java面试题———SpringBoot篇

目录 1、项目中为什么选择SpringBoot 2、SpringBoot的自动装配原理 3、SpringBoot的核心注解是哪个 4、SpringBoot中的starter是干什么的 5、SpringBoot可以有哪些方式加载配置 6、bootstrap.yml和application.yml有何区别 7、SpringBoot读取配置的方式有几种 8、Spring…...

模块化沙箱:构建零信任架构的关键技术

在数字化时代&#xff0c;数据安全成为了企业和机构关注的焦点。模块化沙箱作为一种创新的数据安全解决方案&#xff0c;正逐渐成为保护敏感信息的有力工具。深信达模块化沙箱&#xff0c;凭借其高灵活性和高扩展性&#xff0c;为不同安全需求提供了定制化的解决方案。 模块化沙…...

10.14学习日志

一.矩阵 接上篇 11.伴随矩阵 设 A 是一个 nn 的方阵&#xff0c;其元素为 aij。伴随矩阵 adj(A)或A* 是一个 nn的矩阵&#xff0c;其第 i 行第 j 列的元素是 A 的余子式 Mji 的代数余子式 Cji&#xff0c;即&#xff1a; 其中 Mji是 A 的第j 行第i 列元素的余子式&#xff0…...

“我们为什么缺少科学精神”演讲内容拆解

演讲人张双南&#xff0c;视频链接&#xff1a; https://tv.cctv.com/2017/04/23/VIDEdqzdpmxStYXAmYBdgDP7170423.shtml...

openpyxl 3.0.7 中文教程

openpyxl 3.0.7 中文教程 python Execl 处理库教程 https://openpyxl-chinese-docs.readthedocs.io/zh-cn/latest/tutorial.html#id2 案例&#xff1a; 生成表格&#xff0c;设置单元格样式 from openpyxl import Workbook from openpyxl.styles import Font, Border, Side, …...

idea开发工具使用

idea开发工具使用 1.idea下载 2.idea设置 字体 编码格式 换行 忽略大小写 自动导包 各方法之间加横线 3.快捷键 4.导入工程 5.安装scala插件 6.运行代码 7.导入jar包 8.git托管 9.打jar包...

Android map 获取值

Android Map 获取值的完整指南 在Android开发中&#xff0c;使用Map&#xff08;映射&#xff09;来存储和检索数据是非常常见的需求。Map是一种键值对集合&#xff0c;能够快速而高效地根据特定的键获取值。在这篇文章中&#xff0c;我们将深入探讨如何在Android应用中使用Ma…...