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对象创建之门的钥匙

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

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

相关文章

IPV6学习汇总

一、ICMPV6 ICMPv6&#xff08;Internet Control Message Protocol version 6&#xff09;&#xff0c;即互联网控制信息协议版本六&#xff0c;是为了与IPv6配套使用而开发的互联网控制信息协议。以下是关于ICMPv6的详细介绍&#xff1a; 一、基本功能 ICMPv6向源节点报告关…

半小时速通RHCSA

1-7章: #01创建以上目录和文件结构&#xff0c;并将/yasuo目录拷贝4份到/目录下 #02查看系统合法shell #03查看系统发行版版本 #04查看系统内核版本 #05临时修改主机名 #06查看系统指令的查找路径 #07查看passwd指令的执行路径 #08为/yasuo/ssh_config文件在/mulu目录下创建软链…

Vulnhub:DarkHole_2

一.信息收集/站点收集 &#xff08;1&#xff09;根据物理地址用nmap的主机发现功能得出IP地址 nmap -P 192.168.138.0/24 //同网段下主机发现得到IP为192.168.138.185&#xff08;2&#xff09;做nmap的目录扫描和端口扫描来发现其他站带以及信息 nmap -p- 192.168.138.185 …

什么是DApp?DApp开发指南

一、什么是DApp&#xff1f; DApp&#xff08;Decentralized Application&#xff09;&#xff0c;即去中心化应用&#xff0c;是一种基于区块链技术开发的应用程序&#xff0c;与传统的中心化应用不同&#xff0c;DApp不依赖单一服务器或管理主体&#xff0c;而是利用去中心化…

Oracle数据库安装Windows版本

1.下载压缩包 首先下载oracle19c的数据库&#xff0c;可以在官网下载&#xff0c;也可以从我的百度网盘下载。文件比较大&#xff0c;从oracle官网&#xff08;外网&#xff09;下载速度比较慢&#xff0c;还需要注册oracle用户。 通过网盘分享的文件&#xff1a;oracle数据库…

路由器概述

一、路由器的工作原理 根据路由表转发数据 二、路由表与其形成 2.1路由表 &#xff08;1&#xff09;概念 路由&#xff1a;从源主机到目的主机的转发过程路由表&#xff1a;路由器中维护的路由条目的集合&#xff1b;路由器根据路由表做路径选择 &#xff08;2&#xff…

k8s、prometheus、grafana数据采集和展示的链路流程

k8s集群中&#xff0c;容器级别的数据采集是由cAdvisor程序实现 cAdvisor # Container Advisor 容器顾问 cAdvisor程序是kubelet组件的一部分。 每个节点&#xff0c;包括master节点&#xff0c;都有一个kubelet系统服务&#xff0c; kukelet负责管理pod和容…

多台服务器分布式定时调度的几种方案

背景&#xff1a;现在有多个后端服务器&#xff0c;并且在代码中定义了一个定时任务&#xff0c;希望这个定时任务在一个时间只在一个服务器上执行&#xff0c;涉及到分布式调度&#xff0c;调研了一下总结出几种方案&#xff1a; 1.mysql的内置GET_LOCK GET_LOCK方法的介绍 …

TCP/IP相关

1、关于三次握手、四次挥手和TCP的11种状态&#xff1a; 记住这张图就行了&#xff1a; 2、关于慢启动、拥塞避免、超时重传、快速重传、快速恢复 记住这张图就行了&#xff1a; 一些名词解释&#xff1a; MSS&#xff1a;Maximum Segment Size&#xff0c;最大报文长度 RT…

[论文阅读]SCOTT: Self-Consistent Chain-of-Thought Distillation

中文译名&#xff1a;SCOTT: 思维链一致性蒸馏 会议&#xff1a;Proceedings of the 61st Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers) 链接&#xff1a;SCOTT: Self-Consistent Chain-of-Thought Distillation - ACL Antholo…

简单概述Ton链开发路径

区块链开发领域发展迅速&#xff0c;各种平台为开发人员提供不同的生态系统。其中一个更有趣且越来越相关的区块链是TON&#xff08;开放网络&#xff09;区块链。TON 区块链最初由 Telegram 构思&#xff0c;旨在提供快速、安全且可扩展的去中心化应用程序 (dApp)。凭借其独特…

CSS简单入门

一.简单概念 1.概念 层叠样式表&#xff0c;一种样式表语言&#xff0c;用来美化HTML文档的呈现。 2.书写位置 title标签下方添加style双标签&#xff0c;style标签里面书写CSS代码 &#xff08;1&#xff09;外部学习样式 <title>CSS使用</title> <sty…

【2022统考真题】计算时间复杂度

目录 一、题目描述 二、思路分析 三、易错提醒 四、同级和嵌套的关系 一、题目描述 下列程序段的时间复杂度是&#xff08;&#xff09; int sum 0; for (int i 1; i < n; i * 2) for (int j 0; j < i; j) sum; A. O(logn) B. O(n) C. O(nlogn) D…

前端转换double数据,保留两位小数

Number Number(1.00) 1 Number(1.10) 1.1 Number(1.101) 1.101 要想前端展示页面按 1.00展示1&#xff0c;1.10 展示1.1 需要套一个number() 1.1 保留两位小数&#xff0c;并三位一个分隔符 indexView.value[key] formatNumber(indexView.value[key].toFixed(2))//格式…

聚类分析 | WOA-K-means++聚类优化算法

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 (创新)WOA-K-means聚类优化算法 (WOA聚类优化&#xff0c;创新&#xff0c;独家) 鲸鱼算法优化K-means聚类优化算法 matlab语言&#xff0c;一键出图&#xff0c;直接运行 1.鲸鱼算法WOA作为群智能算法简单高效&a…

25.2 采集端高基数的现象和原因

本节重点介绍 : 什么是高基数采集端高基数的原因 标签的值过多 获取采集端的高基数metrics tsdb-status页面介绍统计原理讲解&#xff1a;是基于内存中的倒排索引 算最大堆取 top10通过接口获取metrics name top10 什么是高基数 通俗的说就是返回的series或者查询到的serie…

spring boot itext7 修改生成文档的作者、制作者、标题,并且读取相关的信息。

1、官方的example文件&#xff1a;iText GitHub itext-java-7.2.5\kernel\src\test\java\com\itextpdf\kernel\pdf\PdfStampingTest.java 2、修改代码&#xff1a; Testpublic void stamping1() throws IOException {String filename1 destinationFolder "stamping1_…

【安装教程】Windows10环境下Pytorch(GPU版)的安装与配置

目录 Pytorch的概念安装前要求一、NVIDIA驱动查看二、Anaconda的安装2.1 Anaconda的安装2.2 创建虚拟环境2.3 激活虚拟环境 三、CUDA ToolKit的安装&#xff08;选做&#xff0c;CPU版本可跳过&#xff09;3.1 CUDA安装包的下载&#xff08;以CUDA11.6.0为例&#xff09;3.2 CU…

【兼容多端】UNIAPP popper气泡弹层vue3+typescript unibest

最近要实习一个泡泡弹层。看了下市场的代码&#xff0c;要么写的不怎么好&#xff0c;要么过于复杂。于是拿个轮子自己加工。200行代码撸了个弹出层组件。兼容H5和APP和小程序。 功能&#xff1a; 1)只支持上下左右4个方向的弹层不支持侧边靠齐 2)不对屏幕边界适配 3)支持弹层…

EmEditor传奇脚本编辑器

主程序&#xff1a;EmEditor.exe 目前已有功能 可以自己指定一个快捷键 实现以下功能&#xff08;默认快捷键为&#xff1a;F1&#xff09; 以下全功能 都是鼠标所在行 按快捷键 &#xff08;默认快捷键&#xff1a;F1&#xff09; 1.在Merchant.txt中 一键打开NPC 没有…